diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-12 17:49:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-12 17:49:56 -0500 |
commit | eea0cf3fcd3243666e0bb792c560ec128b1f06a1 (patch) | |
tree | 2e3cebe332ff4a6898286c6e93f798655368286b | |
parent | 823e334ecd247dd49ca2c5c90414435d77135340 (diff) | |
parent | 95c97b5941542a4dedb22649adea98e25a88923e (diff) |
Merge tag 'for-linus' of git://git.code.sf.net/p/openipmi/linux-ipmi
Pull IPMI driver updates from Corey Minyard:
- Quite a few bug fixes
- A new driver for the powernv
- A new driver for the SMBus interface from the IPMI 2.0 specification
* tag 'for-linus' of git://git.code.sf.net/p/openipmi/linux-ipmi:
ipmi: Check the BT interrupt enable periodically
ipmi: Fix attention handling for system interfaces
ipmi: Periodically check to see if irqs and messages are set right
drivers/char/ipmi: Add powernv IPMI driver
ipmi: Add SMBus interface driver (SSIF)
ipmi: Remove the now unused priority from SMI sender
ipmi: Remove the now unnecessary message queue
ipmi: Make the message handler easier to use for SMI interfaces
ipmi: Move message sending into its own function
ipmi: rename waiting_msgs to waiting_rcv_msgs
ipmi: Fix handling of BMC flags
ipmi: Initialize BMC device attributes
ipmi: Unregister previously registered driver in error case
ipmi: Use the proper type for acpi_handle
ipmi: Fix a bug in hot add/remove
ipmi: Remove useless sysfs_name parameters
ipmi: clean up the device handling for the bmc device
ipmi: Move the address source to string to ipmi-generic code
ipmi: Ignore SSIF in the PNP handling
-rw-r--r-- | Documentation/IPMI.txt | 74 | ||||
-rw-r--r-- | drivers/char/ipmi/Kconfig | 14 | ||||
-rw-r--r-- | drivers/char/ipmi/Makefile | 2 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 560 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_powernv.c | 310 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 497 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_ssif.c | 1870 | ||||
-rw-r--r-- | include/linux/ipmi.h | 6 | ||||
-rw-r--r-- | include/linux/ipmi_smi.h | 10 |
9 files changed, 2828 insertions, 515 deletions
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt index f13c9132e9f2..653d5d739d7f 100644 --- a/Documentation/IPMI.txt +++ b/Documentation/IPMI.txt | |||
@@ -42,7 +42,13 @@ The driver interface depends on your hardware. If your system | |||
42 | properly provides the SMBIOS info for IPMI, the driver will detect it | 42 | properly provides the SMBIOS info for IPMI, the driver will detect it |
43 | and just work. If you have a board with a standard interface (These | 43 | and just work. If you have a board with a standard interface (These |
44 | will generally be either "KCS", "SMIC", or "BT", consult your hardware | 44 | will generally be either "KCS", "SMIC", or "BT", consult your hardware |
45 | manual), choose the 'IPMI SI handler' option. | 45 | manual), choose the 'IPMI SI handler' option. A driver also exists |
46 | for direct I2C access to the IPMI management controller. Some boards | ||
47 | support this, but it is unknown if it will work on every board. For | ||
48 | this, choose 'IPMI SMBus handler', but be ready to try to do some | ||
49 | figuring to see if it will work on your system if the SMBIOS/APCI | ||
50 | information is wrong or not present. It is fairly safe to have both | ||
51 | these enabled and let the drivers auto-detect what is present. | ||
46 | 52 | ||
47 | You should generally enable ACPI on your system, as systems with IPMI | 53 | You should generally enable ACPI on your system, as systems with IPMI |
48 | can have ACPI tables describing them. | 54 | can have ACPI tables describing them. |
@@ -52,7 +58,8 @@ their job correctly, the IPMI controller should be automatically | |||
52 | detected (via ACPI or SMBIOS tables) and should just work. Sadly, | 58 | detected (via ACPI or SMBIOS tables) and should just work. Sadly, |
53 | many boards do not have this information. The driver attempts | 59 | many boards do not have this information. The driver attempts |
54 | standard defaults, but they may not work. If you fall into this | 60 | standard defaults, but they may not work. If you fall into this |
55 | situation, you need to read the section below named 'The SI Driver'. | 61 | situation, you need to read the section below named 'The SI Driver' or |
62 | "The SMBus Driver" on how to hand-configure your system. | ||
56 | 63 | ||
57 | IPMI defines a standard watchdog timer. You can enable this with the | 64 | IPMI defines a standard watchdog timer. You can enable this with the |
58 | 'IPMI Watchdog Timer' config option. If you compile the driver into | 65 | 'IPMI Watchdog Timer' config option. If you compile the driver into |
@@ -97,7 +104,12 @@ driver, each open file for this device ties in to the message handler | |||
97 | as an IPMI user. | 104 | as an IPMI user. |
98 | 105 | ||
99 | ipmi_si - A driver for various system interfaces. This supports KCS, | 106 | ipmi_si - A driver for various system interfaces. This supports KCS, |
100 | SMIC, and BT interfaces. | 107 | SMIC, and BT interfaces. Unless you have an SMBus interface or your |
108 | own custom interface, you probably need to use this. | ||
109 | |||
110 | ipmi_ssif - A driver for accessing BMCs on the SMBus. It uses the | ||
111 | I2C kernel driver's SMBus interfaces to send and receive IPMI messages | ||
112 | over the SMBus. | ||
101 | 113 | ||
102 | ipmi_watchdog - IPMI requires systems to have a very capable watchdog | 114 | ipmi_watchdog - IPMI requires systems to have a very capable watchdog |
103 | timer. This driver implements the standard Linux watchdog timer | 115 | timer. This driver implements the standard Linux watchdog timer |
@@ -476,6 +488,62 @@ for specifying an interface. Note that when removing an interface, | |||
476 | only the first three parameters (si type, address type, and address) | 488 | only the first three parameters (si type, address type, and address) |
477 | are used for the comparison. Any options are ignored for removing. | 489 | are used for the comparison. Any options are ignored for removing. |
478 | 490 | ||
491 | The SMBus Driver (SSIF) | ||
492 | ----------------------- | ||
493 | |||
494 | The SMBus driver allows up to 4 SMBus devices to be configured in the | ||
495 | system. By default, the driver will only register with something it | ||
496 | finds in DMI or ACPI tables. You can change this | ||
497 | at module load time (for a module) with: | ||
498 | |||
499 | modprobe ipmi_ssif.o | ||
500 | addr=<i2caddr1>[,<i2caddr2>[,...]] | ||
501 | adapter=<adapter1>[,<adapter2>[...]] | ||
502 | dbg=<flags1>,<flags2>... | ||
503 | slave_addrs=<addr1>,<addr2>,... | ||
504 | [dbg_probe=1] | ||
505 | |||
506 | The addresses are normal I2C addresses. The adapter is the string | ||
507 | name of the adapter, as shown in /sys/class/i2c-adapter/i2c-<n>/name. | ||
508 | It is *NOT* i2c-<n> itself. | ||
509 | |||
510 | The debug flags are bit flags for each BMC found, they are: | ||
511 | IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8 | ||
512 | |||
513 | Setting dbg_probe to 1 will enable debugging of the probing and | ||
514 | detection process for BMCs on the SMBusses. | ||
515 | |||
516 | The slave_addrs specifies the IPMI address of the local BMC. This is | ||
517 | usually 0x20 and the driver defaults to that, but in case it's not, it | ||
518 | can be specified when the driver starts up. | ||
519 | |||
520 | Discovering the IPMI compliant BMC on the SMBus can cause devices on | ||
521 | the I2C bus to fail. The SMBus driver writes a "Get Device ID" IPMI | ||
522 | message as a block write to the I2C bus and waits for a response. | ||
523 | This action can be detrimental to some I2C devices. It is highly | ||
524 | recommended that the known I2C address be given to the SMBus driver in | ||
525 | the smb_addr parameter unless you have DMI or ACPI data to tell the | ||
526 | driver what to use. | ||
527 | |||
528 | When compiled into the kernel, the addresses can be specified on the | ||
529 | kernel command line as: | ||
530 | |||
531 | ipmb_ssif.addr=<i2caddr1>[,<i2caddr2>[...]] | ||
532 | ipmi_ssif.adapter=<adapter1>[,<adapter2>[...]] | ||
533 | ipmi_ssif.dbg=<flags1>[,<flags2>[...]] | ||
534 | ipmi_ssif.dbg_probe=1 | ||
535 | ipmi_ssif.slave_addrs=<addr1>[,<addr2>[...]] | ||
536 | |||
537 | These are the same options as on the module command line. | ||
538 | |||
539 | The I2C driver does not support non-blocking access or polling, so | ||
540 | this driver cannod to IPMI panic events, extend the watchdog at panic | ||
541 | time, or other panic-related IPMI functions without special kernel | ||
542 | patches and driver modifications. You can get those at the openipmi | ||
543 | web page. | ||
544 | |||
545 | The driver supports a hot add and remove of interfaces through the I2C | ||
546 | sysfs interface. | ||
479 | 547 | ||
480 | Other Pieces | 548 | Other Pieces |
481 | ------------ | 549 | ------------ |
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index db1c9b7adaa6..6ed9e9fe5233 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig | |||
@@ -62,6 +62,20 @@ config IPMI_SI_PROBE_DEFAULTS | |||
62 | only be available on older systems if the "ipmi_si_intf.trydefaults=1" | 62 | only be available on older systems if the "ipmi_si_intf.trydefaults=1" |
63 | boot argument is passed. | 63 | boot argument is passed. |
64 | 64 | ||
65 | config IPMI_SSIF | ||
66 | tristate 'IPMI SMBus handler (SSIF)' | ||
67 | select I2C | ||
68 | help | ||
69 | Provides a driver for a SMBus interface to a BMC, meaning that you | ||
70 | have a driver that must be accessed over an I2C bus instead of a | ||
71 | standard interface. This module requires I2C support. | ||
72 | |||
73 | config IPMI_POWERNV | ||
74 | depends on PPC_POWERNV | ||
75 | tristate 'POWERNV (OPAL firmware) IPMI interface' | ||
76 | help | ||
77 | Provides a driver for OPAL firmware-based IPMI interfaces. | ||
78 | |||
65 | config IPMI_WATCHDOG | 79 | config IPMI_WATCHDOG |
66 | tristate 'IPMI Watchdog Timer' | 80 | tristate 'IPMI Watchdog Timer' |
67 | help | 81 | help |
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile index 16a93648d54e..f3ffde1f5f1f 100644 --- a/drivers/char/ipmi/Makefile +++ b/drivers/char/ipmi/Makefile | |||
@@ -7,5 +7,7 @@ ipmi_si-y := ipmi_si_intf.o ipmi_kcs_sm.o ipmi_smic_sm.o ipmi_bt_sm.o | |||
7 | obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o | 7 | obj-$(CONFIG_IPMI_HANDLER) += ipmi_msghandler.o |
8 | obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o | 8 | obj-$(CONFIG_IPMI_DEVICE_INTERFACE) += ipmi_devintf.o |
9 | obj-$(CONFIG_IPMI_SI) += ipmi_si.o | 9 | obj-$(CONFIG_IPMI_SI) += ipmi_si.o |
10 | obj-$(CONFIG_IPMI_SSIF) += ipmi_ssif.o | ||
11 | obj-$(CONFIG_IPMI_POWERNV) += ipmi_powernv.o | ||
10 | obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o | 12 | obj-$(CONFIG_IPMI_WATCHDOG) += ipmi_watchdog.o |
11 | obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o | 13 | obj-$(CONFIG_IPMI_POWEROFF) += ipmi_poweroff.o |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index f816211f062f..5fa83f751378 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -56,6 +56,8 @@ static int ipmi_init_msghandler(void); | |||
56 | static void smi_recv_tasklet(unsigned long); | 56 | static void smi_recv_tasklet(unsigned long); |
57 | static void handle_new_recv_msgs(ipmi_smi_t intf); | 57 | static void handle_new_recv_msgs(ipmi_smi_t intf); |
58 | static void need_waiter(ipmi_smi_t intf); | 58 | static void need_waiter(ipmi_smi_t intf); |
59 | static int handle_one_recv_msg(ipmi_smi_t intf, | ||
60 | struct ipmi_smi_msg *msg); | ||
59 | 61 | ||
60 | static int initialized; | 62 | static int initialized; |
61 | 63 | ||
@@ -191,12 +193,12 @@ struct ipmi_proc_entry { | |||
191 | #endif | 193 | #endif |
192 | 194 | ||
193 | struct bmc_device { | 195 | struct bmc_device { |
194 | struct platform_device *dev; | 196 | struct platform_device pdev; |
195 | struct ipmi_device_id id; | 197 | struct ipmi_device_id id; |
196 | unsigned char guid[16]; | 198 | unsigned char guid[16]; |
197 | int guid_set; | 199 | int guid_set; |
198 | 200 | char name[16]; | |
199 | struct kref refcount; | 201 | struct kref usecount; |
200 | 202 | ||
201 | /* bmc device attributes */ | 203 | /* bmc device attributes */ |
202 | struct device_attribute device_id_attr; | 204 | struct device_attribute device_id_attr; |
@@ -210,6 +212,7 @@ struct bmc_device { | |||
210 | struct device_attribute guid_attr; | 212 | struct device_attribute guid_attr; |
211 | struct device_attribute aux_firmware_rev_attr; | 213 | struct device_attribute aux_firmware_rev_attr; |
212 | }; | 214 | }; |
215 | #define to_bmc_device(x) container_of((x), struct bmc_device, pdev.dev) | ||
213 | 216 | ||
214 | /* | 217 | /* |
215 | * Various statistics for IPMI, these index stats[] in the ipmi_smi | 218 | * Various statistics for IPMI, these index stats[] in the ipmi_smi |
@@ -323,6 +326,9 @@ struct ipmi_smi { | |||
323 | 326 | ||
324 | struct kref refcount; | 327 | struct kref refcount; |
325 | 328 | ||
329 | /* Set when the interface is being unregistered. */ | ||
330 | bool in_shutdown; | ||
331 | |||
326 | /* Used for a list of interfaces. */ | 332 | /* Used for a list of interfaces. */ |
327 | struct list_head link; | 333 | struct list_head link; |
328 | 334 | ||
@@ -341,7 +347,6 @@ struct ipmi_smi { | |||
341 | 347 | ||
342 | struct bmc_device *bmc; | 348 | struct bmc_device *bmc; |
343 | char *my_dev_name; | 349 | char *my_dev_name; |
344 | char *sysfs_name; | ||
345 | 350 | ||
346 | /* | 351 | /* |
347 | * This is the lower-layer's sender routine. Note that you | 352 | * This is the lower-layer's sender routine. Note that you |
@@ -377,11 +382,16 @@ struct ipmi_smi { | |||
377 | * periodic timer interrupt. The tasklet is for handling received | 382 | * periodic timer interrupt. The tasklet is for handling received |
378 | * messages directly from the handler. | 383 | * messages directly from the handler. |
379 | */ | 384 | */ |
380 | spinlock_t waiting_msgs_lock; | 385 | spinlock_t waiting_rcv_msgs_lock; |
381 | struct list_head waiting_msgs; | 386 | struct list_head waiting_rcv_msgs; |
382 | atomic_t watchdog_pretimeouts_to_deliver; | 387 | atomic_t watchdog_pretimeouts_to_deliver; |
383 | struct tasklet_struct recv_tasklet; | 388 | struct tasklet_struct recv_tasklet; |
384 | 389 | ||
390 | spinlock_t xmit_msgs_lock; | ||
391 | struct list_head xmit_msgs; | ||
392 | struct ipmi_smi_msg *curr_msg; | ||
393 | struct list_head hp_xmit_msgs; | ||
394 | |||
385 | /* | 395 | /* |
386 | * The list of command receivers that are registered for commands | 396 | * The list of command receivers that are registered for commands |
387 | * on this interface. | 397 | * on this interface. |
@@ -474,6 +484,18 @@ static DEFINE_MUTEX(smi_watchers_mutex); | |||
474 | #define ipmi_get_stat(intf, stat) \ | 484 | #define ipmi_get_stat(intf, stat) \ |
475 | ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat])) | 485 | ((unsigned int) atomic_read(&(intf)->stats[IPMI_STAT_ ## stat])) |
476 | 486 | ||
487 | static char *addr_src_to_str[] = { "invalid", "hotmod", "hardcoded", "SPMI", | ||
488 | "ACPI", "SMBIOS", "PCI", | ||
489 | "device-tree", "default" }; | ||
490 | |||
491 | const char *ipmi_addr_src_to_str(enum ipmi_addr_src src) | ||
492 | { | ||
493 | if (src > SI_DEFAULT) | ||
494 | src = 0; /* Invalid */ | ||
495 | return addr_src_to_str[src]; | ||
496 | } | ||
497 | EXPORT_SYMBOL(ipmi_addr_src_to_str); | ||
498 | |||
477 | static int is_lan_addr(struct ipmi_addr *addr) | 499 | static int is_lan_addr(struct ipmi_addr *addr) |
478 | { | 500 | { |
479 | return addr->addr_type == IPMI_LAN_ADDR_TYPE; | 501 | return addr->addr_type == IPMI_LAN_ADDR_TYPE; |
@@ -517,7 +539,7 @@ static void clean_up_interface_data(ipmi_smi_t intf) | |||
517 | 539 | ||
518 | tasklet_kill(&intf->recv_tasklet); | 540 | tasklet_kill(&intf->recv_tasklet); |
519 | 541 | ||
520 | free_smi_msg_list(&intf->waiting_msgs); | 542 | free_smi_msg_list(&intf->waiting_rcv_msgs); |
521 | free_recv_msg_list(&intf->waiting_events); | 543 | free_recv_msg_list(&intf->waiting_events); |
522 | 544 | ||
523 | /* | 545 | /* |
@@ -1473,6 +1495,30 @@ static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg, | |||
1473 | smi_msg->msgid = msgid; | 1495 | smi_msg->msgid = msgid; |
1474 | } | 1496 | } |
1475 | 1497 | ||
1498 | static void smi_send(ipmi_smi_t intf, struct ipmi_smi_handlers *handlers, | ||
1499 | struct ipmi_smi_msg *smi_msg, int priority) | ||
1500 | { | ||
1501 | int run_to_completion = intf->run_to_completion; | ||
1502 | unsigned long flags; | ||
1503 | |||
1504 | if (!run_to_completion) | ||
1505 | spin_lock_irqsave(&intf->xmit_msgs_lock, flags); | ||
1506 | if (intf->curr_msg) { | ||
1507 | if (priority > 0) | ||
1508 | list_add_tail(&smi_msg->link, &intf->hp_xmit_msgs); | ||
1509 | else | ||
1510 | list_add_tail(&smi_msg->link, &intf->xmit_msgs); | ||
1511 | smi_msg = NULL; | ||
1512 | } else { | ||
1513 | intf->curr_msg = smi_msg; | ||
1514 | } | ||
1515 | if (!run_to_completion) | ||
1516 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); | ||
1517 | |||
1518 | if (smi_msg) | ||
1519 | handlers->sender(intf->send_info, smi_msg); | ||
1520 | } | ||
1521 | |||
1476 | /* | 1522 | /* |
1477 | * Separate from ipmi_request so that the user does not have to be | 1523 | * Separate from ipmi_request so that the user does not have to be |
1478 | * supplied in certain circumstances (mainly at panic time). If | 1524 | * supplied in certain circumstances (mainly at panic time). If |
@@ -1497,7 +1543,6 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1497 | struct ipmi_smi_msg *smi_msg; | 1543 | struct ipmi_smi_msg *smi_msg; |
1498 | struct ipmi_recv_msg *recv_msg; | 1544 | struct ipmi_recv_msg *recv_msg; |
1499 | unsigned long flags; | 1545 | unsigned long flags; |
1500 | struct ipmi_smi_handlers *handlers; | ||
1501 | 1546 | ||
1502 | 1547 | ||
1503 | if (supplied_recv) | 1548 | if (supplied_recv) |
@@ -1520,8 +1565,7 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1520 | } | 1565 | } |
1521 | 1566 | ||
1522 | rcu_read_lock(); | 1567 | rcu_read_lock(); |
1523 | handlers = intf->handlers; | 1568 | if (intf->in_shutdown) { |
1524 | if (!handlers) { | ||
1525 | rv = -ENODEV; | 1569 | rv = -ENODEV; |
1526 | goto out_err; | 1570 | goto out_err; |
1527 | } | 1571 | } |
@@ -1856,7 +1900,7 @@ static int i_ipmi_request(ipmi_user_t user, | |||
1856 | } | 1900 | } |
1857 | #endif | 1901 | #endif |
1858 | 1902 | ||
1859 | handlers->sender(intf->send_info, smi_msg, priority); | 1903 | smi_send(intf, intf->handlers, smi_msg, priority); |
1860 | rcu_read_unlock(); | 1904 | rcu_read_unlock(); |
1861 | 1905 | ||
1862 | return 0; | 1906 | return 0; |
@@ -2153,7 +2197,7 @@ static void remove_proc_entries(ipmi_smi_t smi) | |||
2153 | static int __find_bmc_guid(struct device *dev, void *data) | 2197 | static int __find_bmc_guid(struct device *dev, void *data) |
2154 | { | 2198 | { |
2155 | unsigned char *id = data; | 2199 | unsigned char *id = data; |
2156 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2200 | struct bmc_device *bmc = to_bmc_device(dev); |
2157 | return memcmp(bmc->guid, id, 16) == 0; | 2201 | return memcmp(bmc->guid, id, 16) == 0; |
2158 | } | 2202 | } |
2159 | 2203 | ||
@@ -2164,7 +2208,7 @@ static struct bmc_device *ipmi_find_bmc_guid(struct device_driver *drv, | |||
2164 | 2208 | ||
2165 | dev = driver_find_device(drv, NULL, guid, __find_bmc_guid); | 2209 | dev = driver_find_device(drv, NULL, guid, __find_bmc_guid); |
2166 | if (dev) | 2210 | if (dev) |
2167 | return dev_get_drvdata(dev); | 2211 | return to_bmc_device(dev); |
2168 | else | 2212 | else |
2169 | return NULL; | 2213 | return NULL; |
2170 | } | 2214 | } |
@@ -2177,7 +2221,7 @@ struct prod_dev_id { | |||
2177 | static int __find_bmc_prod_dev_id(struct device *dev, void *data) | 2221 | static int __find_bmc_prod_dev_id(struct device *dev, void *data) |
2178 | { | 2222 | { |
2179 | struct prod_dev_id *id = data; | 2223 | struct prod_dev_id *id = data; |
2180 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2224 | struct bmc_device *bmc = to_bmc_device(dev); |
2181 | 2225 | ||
2182 | return (bmc->id.product_id == id->product_id | 2226 | return (bmc->id.product_id == id->product_id |
2183 | && bmc->id.device_id == id->device_id); | 2227 | && bmc->id.device_id == id->device_id); |
@@ -2195,7 +2239,7 @@ static struct bmc_device *ipmi_find_bmc_prod_dev_id( | |||
2195 | 2239 | ||
2196 | dev = driver_find_device(drv, NULL, &id, __find_bmc_prod_dev_id); | 2240 | dev = driver_find_device(drv, NULL, &id, __find_bmc_prod_dev_id); |
2197 | if (dev) | 2241 | if (dev) |
2198 | return dev_get_drvdata(dev); | 2242 | return to_bmc_device(dev); |
2199 | else | 2243 | else |
2200 | return NULL; | 2244 | return NULL; |
2201 | } | 2245 | } |
@@ -2204,84 +2248,92 @@ static ssize_t device_id_show(struct device *dev, | |||
2204 | struct device_attribute *attr, | 2248 | struct device_attribute *attr, |
2205 | char *buf) | 2249 | char *buf) |
2206 | { | 2250 | { |
2207 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2251 | struct bmc_device *bmc = to_bmc_device(dev); |
2208 | 2252 | ||
2209 | return snprintf(buf, 10, "%u\n", bmc->id.device_id); | 2253 | return snprintf(buf, 10, "%u\n", bmc->id.device_id); |
2210 | } | 2254 | } |
2255 | DEVICE_ATTR(device_id, S_IRUGO, device_id_show, NULL); | ||
2211 | 2256 | ||
2212 | static ssize_t provides_dev_sdrs_show(struct device *dev, | 2257 | static ssize_t provides_device_sdrs_show(struct device *dev, |
2213 | struct device_attribute *attr, | 2258 | struct device_attribute *attr, |
2214 | char *buf) | 2259 | char *buf) |
2215 | { | 2260 | { |
2216 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2261 | struct bmc_device *bmc = to_bmc_device(dev); |
2217 | 2262 | ||
2218 | return snprintf(buf, 10, "%u\n", | 2263 | return snprintf(buf, 10, "%u\n", |
2219 | (bmc->id.device_revision & 0x80) >> 7); | 2264 | (bmc->id.device_revision & 0x80) >> 7); |
2220 | } | 2265 | } |
2266 | DEVICE_ATTR(provides_device_sdrs, S_IRUGO, provides_device_sdrs_show, NULL); | ||
2221 | 2267 | ||
2222 | static ssize_t revision_show(struct device *dev, struct device_attribute *attr, | 2268 | static ssize_t revision_show(struct device *dev, struct device_attribute *attr, |
2223 | char *buf) | 2269 | char *buf) |
2224 | { | 2270 | { |
2225 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2271 | struct bmc_device *bmc = to_bmc_device(dev); |
2226 | 2272 | ||
2227 | return snprintf(buf, 20, "%u\n", | 2273 | return snprintf(buf, 20, "%u\n", |
2228 | bmc->id.device_revision & 0x0F); | 2274 | bmc->id.device_revision & 0x0F); |
2229 | } | 2275 | } |
2276 | DEVICE_ATTR(revision, S_IRUGO, revision_show, NULL); | ||
2230 | 2277 | ||
2231 | static ssize_t firmware_rev_show(struct device *dev, | 2278 | static ssize_t firmware_revision_show(struct device *dev, |
2232 | struct device_attribute *attr, | 2279 | struct device_attribute *attr, |
2233 | char *buf) | 2280 | char *buf) |
2234 | { | 2281 | { |
2235 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2282 | struct bmc_device *bmc = to_bmc_device(dev); |
2236 | 2283 | ||
2237 | return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1, | 2284 | return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1, |
2238 | bmc->id.firmware_revision_2); | 2285 | bmc->id.firmware_revision_2); |
2239 | } | 2286 | } |
2287 | DEVICE_ATTR(firmware_revision, S_IRUGO, firmware_revision_show, NULL); | ||
2240 | 2288 | ||
2241 | static ssize_t ipmi_version_show(struct device *dev, | 2289 | static ssize_t ipmi_version_show(struct device *dev, |
2242 | struct device_attribute *attr, | 2290 | struct device_attribute *attr, |
2243 | char *buf) | 2291 | char *buf) |
2244 | { | 2292 | { |
2245 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2293 | struct bmc_device *bmc = to_bmc_device(dev); |
2246 | 2294 | ||
2247 | return snprintf(buf, 20, "%u.%u\n", | 2295 | return snprintf(buf, 20, "%u.%u\n", |
2248 | ipmi_version_major(&bmc->id), | 2296 | ipmi_version_major(&bmc->id), |
2249 | ipmi_version_minor(&bmc->id)); | 2297 | ipmi_version_minor(&bmc->id)); |
2250 | } | 2298 | } |
2299 | DEVICE_ATTR(ipmi_version, S_IRUGO, ipmi_version_show, NULL); | ||
2251 | 2300 | ||
2252 | static ssize_t add_dev_support_show(struct device *dev, | 2301 | static ssize_t add_dev_support_show(struct device *dev, |
2253 | struct device_attribute *attr, | 2302 | struct device_attribute *attr, |
2254 | char *buf) | 2303 | char *buf) |
2255 | { | 2304 | { |
2256 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2305 | struct bmc_device *bmc = to_bmc_device(dev); |
2257 | 2306 | ||
2258 | return snprintf(buf, 10, "0x%02x\n", | 2307 | return snprintf(buf, 10, "0x%02x\n", |
2259 | bmc->id.additional_device_support); | 2308 | bmc->id.additional_device_support); |
2260 | } | 2309 | } |
2310 | DEVICE_ATTR(additional_device_support, S_IRUGO, add_dev_support_show, NULL); | ||
2261 | 2311 | ||
2262 | static ssize_t manufacturer_id_show(struct device *dev, | 2312 | static ssize_t manufacturer_id_show(struct device *dev, |
2263 | struct device_attribute *attr, | 2313 | struct device_attribute *attr, |
2264 | char *buf) | 2314 | char *buf) |
2265 | { | 2315 | { |
2266 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2316 | struct bmc_device *bmc = to_bmc_device(dev); |
2267 | 2317 | ||
2268 | return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id); | 2318 | return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id); |
2269 | } | 2319 | } |
2320 | DEVICE_ATTR(manufacturer_id, S_IRUGO, manufacturer_id_show, NULL); | ||
2270 | 2321 | ||
2271 | static ssize_t product_id_show(struct device *dev, | 2322 | static ssize_t product_id_show(struct device *dev, |
2272 | struct device_attribute *attr, | 2323 | struct device_attribute *attr, |
2273 | char *buf) | 2324 | char *buf) |
2274 | { | 2325 | { |
2275 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2326 | struct bmc_device *bmc = to_bmc_device(dev); |
2276 | 2327 | ||
2277 | return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id); | 2328 | return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id); |
2278 | } | 2329 | } |
2330 | DEVICE_ATTR(product_id, S_IRUGO, product_id_show, NULL); | ||
2279 | 2331 | ||
2280 | static ssize_t aux_firmware_rev_show(struct device *dev, | 2332 | static ssize_t aux_firmware_rev_show(struct device *dev, |
2281 | struct device_attribute *attr, | 2333 | struct device_attribute *attr, |
2282 | char *buf) | 2334 | char *buf) |
2283 | { | 2335 | { |
2284 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2336 | struct bmc_device *bmc = to_bmc_device(dev); |
2285 | 2337 | ||
2286 | return snprintf(buf, 21, "0x%02x 0x%02x 0x%02x 0x%02x\n", | 2338 | return snprintf(buf, 21, "0x%02x 0x%02x 0x%02x 0x%02x\n", |
2287 | bmc->id.aux_firmware_revision[3], | 2339 | bmc->id.aux_firmware_revision[3], |
@@ -2289,174 +2341,96 @@ static ssize_t aux_firmware_rev_show(struct device *dev, | |||
2289 | bmc->id.aux_firmware_revision[1], | 2341 | bmc->id.aux_firmware_revision[1], |
2290 | bmc->id.aux_firmware_revision[0]); | 2342 | bmc->id.aux_firmware_revision[0]); |
2291 | } | 2343 | } |
2344 | DEVICE_ATTR(aux_firmware_revision, S_IRUGO, aux_firmware_rev_show, NULL); | ||
2292 | 2345 | ||
2293 | static ssize_t guid_show(struct device *dev, struct device_attribute *attr, | 2346 | static ssize_t guid_show(struct device *dev, struct device_attribute *attr, |
2294 | char *buf) | 2347 | char *buf) |
2295 | { | 2348 | { |
2296 | struct bmc_device *bmc = dev_get_drvdata(dev); | 2349 | struct bmc_device *bmc = to_bmc_device(dev); |
2297 | 2350 | ||
2298 | return snprintf(buf, 100, "%Lx%Lx\n", | 2351 | return snprintf(buf, 100, "%Lx%Lx\n", |
2299 | (long long) bmc->guid[0], | 2352 | (long long) bmc->guid[0], |
2300 | (long long) bmc->guid[8]); | 2353 | (long long) bmc->guid[8]); |
2301 | } | 2354 | } |
2355 | DEVICE_ATTR(guid, S_IRUGO, guid_show, NULL); | ||
2356 | |||
2357 | static struct attribute *bmc_dev_attrs[] = { | ||
2358 | &dev_attr_device_id.attr, | ||
2359 | &dev_attr_provides_device_sdrs.attr, | ||
2360 | &dev_attr_revision.attr, | ||
2361 | &dev_attr_firmware_revision.attr, | ||
2362 | &dev_attr_ipmi_version.attr, | ||
2363 | &dev_attr_additional_device_support.attr, | ||
2364 | &dev_attr_manufacturer_id.attr, | ||
2365 | &dev_attr_product_id.attr, | ||
2366 | NULL | ||
2367 | }; | ||
2302 | 2368 | ||
2303 | static void remove_files(struct bmc_device *bmc) | 2369 | static struct attribute_group bmc_dev_attr_group = { |
2304 | { | 2370 | .attrs = bmc_dev_attrs, |
2305 | if (!bmc->dev) | 2371 | }; |
2306 | return; | ||
2307 | 2372 | ||
2308 | device_remove_file(&bmc->dev->dev, | 2373 | static const struct attribute_group *bmc_dev_attr_groups[] = { |
2309 | &bmc->device_id_attr); | 2374 | &bmc_dev_attr_group, |
2310 | device_remove_file(&bmc->dev->dev, | 2375 | NULL |
2311 | &bmc->provides_dev_sdrs_attr); | 2376 | }; |
2312 | device_remove_file(&bmc->dev->dev, | ||
2313 | &bmc->revision_attr); | ||
2314 | device_remove_file(&bmc->dev->dev, | ||
2315 | &bmc->firmware_rev_attr); | ||
2316 | device_remove_file(&bmc->dev->dev, | ||
2317 | &bmc->version_attr); | ||
2318 | device_remove_file(&bmc->dev->dev, | ||
2319 | &bmc->add_dev_support_attr); | ||
2320 | device_remove_file(&bmc->dev->dev, | ||
2321 | &bmc->manufacturer_id_attr); | ||
2322 | device_remove_file(&bmc->dev->dev, | ||
2323 | &bmc->product_id_attr); | ||
2324 | 2377 | ||
2325 | if (bmc->id.aux_firmware_revision_set) | 2378 | static struct device_type bmc_device_type = { |
2326 | device_remove_file(&bmc->dev->dev, | 2379 | .groups = bmc_dev_attr_groups, |
2327 | &bmc->aux_firmware_rev_attr); | 2380 | }; |
2328 | if (bmc->guid_set) | 2381 | |
2329 | device_remove_file(&bmc->dev->dev, | 2382 | static void |
2330 | &bmc->guid_attr); | 2383 | release_bmc_device(struct device *dev) |
2384 | { | ||
2385 | kfree(to_bmc_device(dev)); | ||
2331 | } | 2386 | } |
2332 | 2387 | ||
2333 | static void | 2388 | static void |
2334 | cleanup_bmc_device(struct kref *ref) | 2389 | cleanup_bmc_device(struct kref *ref) |
2335 | { | 2390 | { |
2336 | struct bmc_device *bmc; | 2391 | struct bmc_device *bmc = container_of(ref, struct bmc_device, usecount); |
2337 | 2392 | ||
2338 | bmc = container_of(ref, struct bmc_device, refcount); | 2393 | if (bmc->id.aux_firmware_revision_set) |
2394 | device_remove_file(&bmc->pdev.dev, | ||
2395 | &bmc->aux_firmware_rev_attr); | ||
2396 | if (bmc->guid_set) | ||
2397 | device_remove_file(&bmc->pdev.dev, | ||
2398 | &bmc->guid_attr); | ||
2339 | 2399 | ||
2340 | remove_files(bmc); | 2400 | platform_device_unregister(&bmc->pdev); |
2341 | platform_device_unregister(bmc->dev); | ||
2342 | kfree(bmc); | ||
2343 | } | 2401 | } |
2344 | 2402 | ||
2345 | static void ipmi_bmc_unregister(ipmi_smi_t intf) | 2403 | static void ipmi_bmc_unregister(ipmi_smi_t intf) |
2346 | { | 2404 | { |
2347 | struct bmc_device *bmc = intf->bmc; | 2405 | struct bmc_device *bmc = intf->bmc; |
2348 | 2406 | ||
2349 | if (intf->sysfs_name) { | 2407 | sysfs_remove_link(&intf->si_dev->kobj, "bmc"); |
2350 | sysfs_remove_link(&intf->si_dev->kobj, intf->sysfs_name); | ||
2351 | kfree(intf->sysfs_name); | ||
2352 | intf->sysfs_name = NULL; | ||
2353 | } | ||
2354 | if (intf->my_dev_name) { | 2408 | if (intf->my_dev_name) { |
2355 | sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name); | 2409 | sysfs_remove_link(&bmc->pdev.dev.kobj, intf->my_dev_name); |
2356 | kfree(intf->my_dev_name); | 2410 | kfree(intf->my_dev_name); |
2357 | intf->my_dev_name = NULL; | 2411 | intf->my_dev_name = NULL; |
2358 | } | 2412 | } |
2359 | 2413 | ||
2360 | mutex_lock(&ipmidriver_mutex); | 2414 | mutex_lock(&ipmidriver_mutex); |
2361 | kref_put(&bmc->refcount, cleanup_bmc_device); | 2415 | kref_put(&bmc->usecount, cleanup_bmc_device); |
2362 | intf->bmc = NULL; | 2416 | intf->bmc = NULL; |
2363 | mutex_unlock(&ipmidriver_mutex); | 2417 | mutex_unlock(&ipmidriver_mutex); |
2364 | } | 2418 | } |
2365 | 2419 | ||
2366 | static int create_files(struct bmc_device *bmc) | 2420 | static int create_bmc_files(struct bmc_device *bmc) |
2367 | { | 2421 | { |
2368 | int err; | 2422 | int err; |
2369 | 2423 | ||
2370 | bmc->device_id_attr.attr.name = "device_id"; | ||
2371 | bmc->device_id_attr.attr.mode = S_IRUGO; | ||
2372 | bmc->device_id_attr.show = device_id_show; | ||
2373 | sysfs_attr_init(&bmc->device_id_attr.attr); | ||
2374 | |||
2375 | bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; | ||
2376 | bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; | ||
2377 | bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; | ||
2378 | sysfs_attr_init(&bmc->provides_dev_sdrs_attr.attr); | ||
2379 | |||
2380 | bmc->revision_attr.attr.name = "revision"; | ||
2381 | bmc->revision_attr.attr.mode = S_IRUGO; | ||
2382 | bmc->revision_attr.show = revision_show; | ||
2383 | sysfs_attr_init(&bmc->revision_attr.attr); | ||
2384 | |||
2385 | bmc->firmware_rev_attr.attr.name = "firmware_revision"; | ||
2386 | bmc->firmware_rev_attr.attr.mode = S_IRUGO; | ||
2387 | bmc->firmware_rev_attr.show = firmware_rev_show; | ||
2388 | sysfs_attr_init(&bmc->firmware_rev_attr.attr); | ||
2389 | |||
2390 | bmc->version_attr.attr.name = "ipmi_version"; | ||
2391 | bmc->version_attr.attr.mode = S_IRUGO; | ||
2392 | bmc->version_attr.show = ipmi_version_show; | ||
2393 | sysfs_attr_init(&bmc->version_attr.attr); | ||
2394 | |||
2395 | bmc->add_dev_support_attr.attr.name = "additional_device_support"; | ||
2396 | bmc->add_dev_support_attr.attr.mode = S_IRUGO; | ||
2397 | bmc->add_dev_support_attr.show = add_dev_support_show; | ||
2398 | sysfs_attr_init(&bmc->add_dev_support_attr.attr); | ||
2399 | |||
2400 | bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; | ||
2401 | bmc->manufacturer_id_attr.attr.mode = S_IRUGO; | ||
2402 | bmc->manufacturer_id_attr.show = manufacturer_id_show; | ||
2403 | sysfs_attr_init(&bmc->manufacturer_id_attr.attr); | ||
2404 | |||
2405 | bmc->product_id_attr.attr.name = "product_id"; | ||
2406 | bmc->product_id_attr.attr.mode = S_IRUGO; | ||
2407 | bmc->product_id_attr.show = product_id_show; | ||
2408 | sysfs_attr_init(&bmc->product_id_attr.attr); | ||
2409 | |||
2410 | bmc->guid_attr.attr.name = "guid"; | ||
2411 | bmc->guid_attr.attr.mode = S_IRUGO; | ||
2412 | bmc->guid_attr.show = guid_show; | ||
2413 | sysfs_attr_init(&bmc->guid_attr.attr); | ||
2414 | |||
2415 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; | ||
2416 | bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; | ||
2417 | bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; | ||
2418 | sysfs_attr_init(&bmc->aux_firmware_rev_attr.attr); | ||
2419 | |||
2420 | err = device_create_file(&bmc->dev->dev, | ||
2421 | &bmc->device_id_attr); | ||
2422 | if (err) | ||
2423 | goto out; | ||
2424 | err = device_create_file(&bmc->dev->dev, | ||
2425 | &bmc->provides_dev_sdrs_attr); | ||
2426 | if (err) | ||
2427 | goto out_devid; | ||
2428 | err = device_create_file(&bmc->dev->dev, | ||
2429 | &bmc->revision_attr); | ||
2430 | if (err) | ||
2431 | goto out_sdrs; | ||
2432 | err = device_create_file(&bmc->dev->dev, | ||
2433 | &bmc->firmware_rev_attr); | ||
2434 | if (err) | ||
2435 | goto out_rev; | ||
2436 | err = device_create_file(&bmc->dev->dev, | ||
2437 | &bmc->version_attr); | ||
2438 | if (err) | ||
2439 | goto out_firm; | ||
2440 | err = device_create_file(&bmc->dev->dev, | ||
2441 | &bmc->add_dev_support_attr); | ||
2442 | if (err) | ||
2443 | goto out_version; | ||
2444 | err = device_create_file(&bmc->dev->dev, | ||
2445 | &bmc->manufacturer_id_attr); | ||
2446 | if (err) | ||
2447 | goto out_add_dev; | ||
2448 | err = device_create_file(&bmc->dev->dev, | ||
2449 | &bmc->product_id_attr); | ||
2450 | if (err) | ||
2451 | goto out_manu; | ||
2452 | if (bmc->id.aux_firmware_revision_set) { | 2424 | if (bmc->id.aux_firmware_revision_set) { |
2453 | err = device_create_file(&bmc->dev->dev, | 2425 | bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; |
2426 | err = device_create_file(&bmc->pdev.dev, | ||
2454 | &bmc->aux_firmware_rev_attr); | 2427 | &bmc->aux_firmware_rev_attr); |
2455 | if (err) | 2428 | if (err) |
2456 | goto out_prod_id; | 2429 | goto out; |
2457 | } | 2430 | } |
2458 | if (bmc->guid_set) { | 2431 | if (bmc->guid_set) { |
2459 | err = device_create_file(&bmc->dev->dev, | 2432 | bmc->guid_attr.attr.name = "guid"; |
2433 | err = device_create_file(&bmc->pdev.dev, | ||
2460 | &bmc->guid_attr); | 2434 | &bmc->guid_attr); |
2461 | if (err) | 2435 | if (err) |
2462 | goto out_aux_firm; | 2436 | goto out_aux_firm; |
@@ -2466,44 +2440,17 @@ static int create_files(struct bmc_device *bmc) | |||
2466 | 2440 | ||
2467 | out_aux_firm: | 2441 | out_aux_firm: |
2468 | if (bmc->id.aux_firmware_revision_set) | 2442 | if (bmc->id.aux_firmware_revision_set) |
2469 | device_remove_file(&bmc->dev->dev, | 2443 | device_remove_file(&bmc->pdev.dev, |
2470 | &bmc->aux_firmware_rev_attr); | 2444 | &bmc->aux_firmware_rev_attr); |
2471 | out_prod_id: | ||
2472 | device_remove_file(&bmc->dev->dev, | ||
2473 | &bmc->product_id_attr); | ||
2474 | out_manu: | ||
2475 | device_remove_file(&bmc->dev->dev, | ||
2476 | &bmc->manufacturer_id_attr); | ||
2477 | out_add_dev: | ||
2478 | device_remove_file(&bmc->dev->dev, | ||
2479 | &bmc->add_dev_support_attr); | ||
2480 | out_version: | ||
2481 | device_remove_file(&bmc->dev->dev, | ||
2482 | &bmc->version_attr); | ||
2483 | out_firm: | ||
2484 | device_remove_file(&bmc->dev->dev, | ||
2485 | &bmc->firmware_rev_attr); | ||
2486 | out_rev: | ||
2487 | device_remove_file(&bmc->dev->dev, | ||
2488 | &bmc->revision_attr); | ||
2489 | out_sdrs: | ||
2490 | device_remove_file(&bmc->dev->dev, | ||
2491 | &bmc->provides_dev_sdrs_attr); | ||
2492 | out_devid: | ||
2493 | device_remove_file(&bmc->dev->dev, | ||
2494 | &bmc->device_id_attr); | ||
2495 | out: | 2445 | out: |
2496 | return err; | 2446 | return err; |
2497 | } | 2447 | } |
2498 | 2448 | ||
2499 | static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | 2449 | static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum) |
2500 | const char *sysfs_name) | ||
2501 | { | 2450 | { |
2502 | int rv; | 2451 | int rv; |
2503 | struct bmc_device *bmc = intf->bmc; | 2452 | struct bmc_device *bmc = intf->bmc; |
2504 | struct bmc_device *old_bmc; | 2453 | struct bmc_device *old_bmc; |
2505 | int size; | ||
2506 | char dummy[1]; | ||
2507 | 2454 | ||
2508 | mutex_lock(&ipmidriver_mutex); | 2455 | mutex_lock(&ipmidriver_mutex); |
2509 | 2456 | ||
@@ -2527,7 +2474,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2527 | intf->bmc = old_bmc; | 2474 | intf->bmc = old_bmc; |
2528 | bmc = old_bmc; | 2475 | bmc = old_bmc; |
2529 | 2476 | ||
2530 | kref_get(&bmc->refcount); | 2477 | kref_get(&bmc->usecount); |
2531 | mutex_unlock(&ipmidriver_mutex); | 2478 | mutex_unlock(&ipmidriver_mutex); |
2532 | 2479 | ||
2533 | printk(KERN_INFO | 2480 | printk(KERN_INFO |
@@ -2537,12 +2484,12 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2537 | bmc->id.product_id, | 2484 | bmc->id.product_id, |
2538 | bmc->id.device_id); | 2485 | bmc->id.device_id); |
2539 | } else { | 2486 | } else { |
2540 | char name[14]; | ||
2541 | unsigned char orig_dev_id = bmc->id.device_id; | 2487 | unsigned char orig_dev_id = bmc->id.device_id; |
2542 | int warn_printed = 0; | 2488 | int warn_printed = 0; |
2543 | 2489 | ||
2544 | snprintf(name, sizeof(name), | 2490 | snprintf(bmc->name, sizeof(bmc->name), |
2545 | "ipmi_bmc.%4.4x", bmc->id.product_id); | 2491 | "ipmi_bmc.%4.4x", bmc->id.product_id); |
2492 | bmc->pdev.name = bmc->name; | ||
2546 | 2493 | ||
2547 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver.driver, | 2494 | while (ipmi_find_bmc_prod_dev_id(&ipmidriver.driver, |
2548 | bmc->id.product_id, | 2495 | bmc->id.product_id, |
@@ -2566,23 +2513,16 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2566 | } | 2513 | } |
2567 | } | 2514 | } |
2568 | 2515 | ||
2569 | bmc->dev = platform_device_alloc(name, bmc->id.device_id); | 2516 | bmc->pdev.dev.driver = &ipmidriver.driver; |
2570 | if (!bmc->dev) { | 2517 | bmc->pdev.id = bmc->id.device_id; |
2571 | mutex_unlock(&ipmidriver_mutex); | 2518 | bmc->pdev.dev.release = release_bmc_device; |
2572 | printk(KERN_ERR | 2519 | bmc->pdev.dev.type = &bmc_device_type; |
2573 | "ipmi_msghandler:" | 2520 | kref_init(&bmc->usecount); |
2574 | " Unable to allocate platform device\n"); | ||
2575 | return -ENOMEM; | ||
2576 | } | ||
2577 | bmc->dev->dev.driver = &ipmidriver.driver; | ||
2578 | dev_set_drvdata(&bmc->dev->dev, bmc); | ||
2579 | kref_init(&bmc->refcount); | ||
2580 | 2521 | ||
2581 | rv = platform_device_add(bmc->dev); | 2522 | rv = platform_device_register(&bmc->pdev); |
2582 | mutex_unlock(&ipmidriver_mutex); | 2523 | mutex_unlock(&ipmidriver_mutex); |
2583 | if (rv) { | 2524 | if (rv) { |
2584 | platform_device_put(bmc->dev); | 2525 | put_device(&bmc->pdev.dev); |
2585 | bmc->dev = NULL; | ||
2586 | printk(KERN_ERR | 2526 | printk(KERN_ERR |
2587 | "ipmi_msghandler:" | 2527 | "ipmi_msghandler:" |
2588 | " Unable to register bmc device: %d\n", | 2528 | " Unable to register bmc device: %d\n", |
@@ -2594,10 +2534,10 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2594 | return rv; | 2534 | return rv; |
2595 | } | 2535 | } |
2596 | 2536 | ||
2597 | rv = create_files(bmc); | 2537 | rv = create_bmc_files(bmc); |
2598 | if (rv) { | 2538 | if (rv) { |
2599 | mutex_lock(&ipmidriver_mutex); | 2539 | mutex_lock(&ipmidriver_mutex); |
2600 | platform_device_unregister(bmc->dev); | 2540 | platform_device_unregister(&bmc->pdev); |
2601 | mutex_unlock(&ipmidriver_mutex); | 2541 | mutex_unlock(&ipmidriver_mutex); |
2602 | 2542 | ||
2603 | return rv; | 2543 | return rv; |
@@ -2614,44 +2554,26 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2614 | * create symlink from system interface device to bmc device | 2554 | * create symlink from system interface device to bmc device |
2615 | * and back. | 2555 | * and back. |
2616 | */ | 2556 | */ |
2617 | intf->sysfs_name = kstrdup(sysfs_name, GFP_KERNEL); | 2557 | rv = sysfs_create_link(&intf->si_dev->kobj, &bmc->pdev.dev.kobj, "bmc"); |
2618 | if (!intf->sysfs_name) { | ||
2619 | rv = -ENOMEM; | ||
2620 | printk(KERN_ERR | ||
2621 | "ipmi_msghandler: allocate link to BMC: %d\n", | ||
2622 | rv); | ||
2623 | goto out_err; | ||
2624 | } | ||
2625 | |||
2626 | rv = sysfs_create_link(&intf->si_dev->kobj, | ||
2627 | &bmc->dev->dev.kobj, intf->sysfs_name); | ||
2628 | if (rv) { | 2558 | if (rv) { |
2629 | kfree(intf->sysfs_name); | ||
2630 | intf->sysfs_name = NULL; | ||
2631 | printk(KERN_ERR | 2559 | printk(KERN_ERR |
2632 | "ipmi_msghandler: Unable to create bmc symlink: %d\n", | 2560 | "ipmi_msghandler: Unable to create bmc symlink: %d\n", |
2633 | rv); | 2561 | rv); |
2634 | goto out_err; | 2562 | goto out_err; |
2635 | } | 2563 | } |
2636 | 2564 | ||
2637 | size = snprintf(dummy, 0, "ipmi%d", ifnum); | 2565 | intf->my_dev_name = kasprintf(GFP_KERNEL, "ipmi%d", ifnum); |
2638 | intf->my_dev_name = kmalloc(size+1, GFP_KERNEL); | ||
2639 | if (!intf->my_dev_name) { | 2566 | if (!intf->my_dev_name) { |
2640 | kfree(intf->sysfs_name); | ||
2641 | intf->sysfs_name = NULL; | ||
2642 | rv = -ENOMEM; | 2567 | rv = -ENOMEM; |
2643 | printk(KERN_ERR | 2568 | printk(KERN_ERR |
2644 | "ipmi_msghandler: allocate link from BMC: %d\n", | 2569 | "ipmi_msghandler: allocate link from BMC: %d\n", |
2645 | rv); | 2570 | rv); |
2646 | goto out_err; | 2571 | goto out_err; |
2647 | } | 2572 | } |
2648 | snprintf(intf->my_dev_name, size+1, "ipmi%d", ifnum); | ||
2649 | 2573 | ||
2650 | rv = sysfs_create_link(&bmc->dev->dev.kobj, &intf->si_dev->kobj, | 2574 | rv = sysfs_create_link(&bmc->pdev.dev.kobj, &intf->si_dev->kobj, |
2651 | intf->my_dev_name); | 2575 | intf->my_dev_name); |
2652 | if (rv) { | 2576 | if (rv) { |
2653 | kfree(intf->sysfs_name); | ||
2654 | intf->sysfs_name = NULL; | ||
2655 | kfree(intf->my_dev_name); | 2577 | kfree(intf->my_dev_name); |
2656 | intf->my_dev_name = NULL; | 2578 | intf->my_dev_name = NULL; |
2657 | printk(KERN_ERR | 2579 | printk(KERN_ERR |
@@ -2850,7 +2772,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2850 | void *send_info, | 2772 | void *send_info, |
2851 | struct ipmi_device_id *device_id, | 2773 | struct ipmi_device_id *device_id, |
2852 | struct device *si_dev, | 2774 | struct device *si_dev, |
2853 | const char *sysfs_name, | ||
2854 | unsigned char slave_addr) | 2775 | unsigned char slave_addr) |
2855 | { | 2776 | { |
2856 | int i, j; | 2777 | int i, j; |
@@ -2909,12 +2830,15 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2909 | #ifdef CONFIG_PROC_FS | 2830 | #ifdef CONFIG_PROC_FS |
2910 | mutex_init(&intf->proc_entry_lock); | 2831 | mutex_init(&intf->proc_entry_lock); |
2911 | #endif | 2832 | #endif |
2912 | spin_lock_init(&intf->waiting_msgs_lock); | 2833 | spin_lock_init(&intf->waiting_rcv_msgs_lock); |
2913 | INIT_LIST_HEAD(&intf->waiting_msgs); | 2834 | INIT_LIST_HEAD(&intf->waiting_rcv_msgs); |
2914 | tasklet_init(&intf->recv_tasklet, | 2835 | tasklet_init(&intf->recv_tasklet, |
2915 | smi_recv_tasklet, | 2836 | smi_recv_tasklet, |
2916 | (unsigned long) intf); | 2837 | (unsigned long) intf); |
2917 | atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0); | 2838 | atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0); |
2839 | spin_lock_init(&intf->xmit_msgs_lock); | ||
2840 | INIT_LIST_HEAD(&intf->xmit_msgs); | ||
2841 | INIT_LIST_HEAD(&intf->hp_xmit_msgs); | ||
2918 | spin_lock_init(&intf->events_lock); | 2842 | spin_lock_init(&intf->events_lock); |
2919 | atomic_set(&intf->event_waiters, 0); | 2843 | atomic_set(&intf->event_waiters, 0); |
2920 | intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME; | 2844 | intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME; |
@@ -2984,7 +2908,7 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
2984 | if (rv == 0) | 2908 | if (rv == 0) |
2985 | rv = add_proc_entries(intf, i); | 2909 | rv = add_proc_entries(intf, i); |
2986 | 2910 | ||
2987 | rv = ipmi_bmc_register(intf, i, sysfs_name); | 2911 | rv = ipmi_bmc_register(intf, i); |
2988 | 2912 | ||
2989 | out: | 2913 | out: |
2990 | if (rv) { | 2914 | if (rv) { |
@@ -3014,12 +2938,50 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
3014 | } | 2938 | } |
3015 | EXPORT_SYMBOL(ipmi_register_smi); | 2939 | EXPORT_SYMBOL(ipmi_register_smi); |
3016 | 2940 | ||
2941 | static void deliver_smi_err_response(ipmi_smi_t intf, | ||
2942 | struct ipmi_smi_msg *msg, | ||
2943 | unsigned char err) | ||
2944 | { | ||
2945 | msg->rsp[0] = msg->data[0] | 4; | ||
2946 | msg->rsp[1] = msg->data[1]; | ||
2947 | msg->rsp[2] = err; | ||
2948 | msg->rsp_size = 3; | ||
2949 | /* It's an error, so it will never requeue, no need to check return. */ | ||
2950 | handle_one_recv_msg(intf, msg); | ||
2951 | } | ||
2952 | |||
3017 | static void cleanup_smi_msgs(ipmi_smi_t intf) | 2953 | static void cleanup_smi_msgs(ipmi_smi_t intf) |
3018 | { | 2954 | { |
3019 | int i; | 2955 | int i; |
3020 | struct seq_table *ent; | 2956 | struct seq_table *ent; |
2957 | struct ipmi_smi_msg *msg; | ||
2958 | struct list_head *entry; | ||
2959 | struct list_head tmplist; | ||
2960 | |||
2961 | /* Clear out our transmit queues and hold the messages. */ | ||
2962 | INIT_LIST_HEAD(&tmplist); | ||
2963 | list_splice_tail(&intf->hp_xmit_msgs, &tmplist); | ||
2964 | list_splice_tail(&intf->xmit_msgs, &tmplist); | ||
2965 | |||
2966 | /* Current message first, to preserve order */ | ||
2967 | while (intf->curr_msg && !list_empty(&intf->waiting_rcv_msgs)) { | ||
2968 | /* Wait for the message to clear out. */ | ||
2969 | schedule_timeout(1); | ||
2970 | } | ||
3021 | 2971 | ||
3022 | /* No need for locks, the interface is down. */ | 2972 | /* No need for locks, the interface is down. */ |
2973 | |||
2974 | /* | ||
2975 | * Return errors for all pending messages in queue and in the | ||
2976 | * tables waiting for remote responses. | ||
2977 | */ | ||
2978 | while (!list_empty(&tmplist)) { | ||
2979 | entry = tmplist.next; | ||
2980 | list_del(entry); | ||
2981 | msg = list_entry(entry, struct ipmi_smi_msg, link); | ||
2982 | deliver_smi_err_response(intf, msg, IPMI_ERR_UNSPECIFIED); | ||
2983 | } | ||
2984 | |||
3023 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { | 2985 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { |
3024 | ent = &(intf->seq_table[i]); | 2986 | ent = &(intf->seq_table[i]); |
3025 | if (!ent->inuse) | 2987 | if (!ent->inuse) |
@@ -3031,20 +2993,33 @@ static void cleanup_smi_msgs(ipmi_smi_t intf) | |||
3031 | int ipmi_unregister_smi(ipmi_smi_t intf) | 2993 | int ipmi_unregister_smi(ipmi_smi_t intf) |
3032 | { | 2994 | { |
3033 | struct ipmi_smi_watcher *w; | 2995 | struct ipmi_smi_watcher *w; |
3034 | int intf_num = intf->intf_num; | 2996 | int intf_num = intf->intf_num; |
2997 | ipmi_user_t user; | ||
3035 | 2998 | ||
3036 | ipmi_bmc_unregister(intf); | 2999 | ipmi_bmc_unregister(intf); |
3037 | 3000 | ||
3038 | mutex_lock(&smi_watchers_mutex); | 3001 | mutex_lock(&smi_watchers_mutex); |
3039 | mutex_lock(&ipmi_interfaces_mutex); | 3002 | mutex_lock(&ipmi_interfaces_mutex); |
3040 | intf->intf_num = -1; | 3003 | intf->intf_num = -1; |
3041 | intf->handlers = NULL; | 3004 | intf->in_shutdown = true; |
3042 | list_del_rcu(&intf->link); | 3005 | list_del_rcu(&intf->link); |
3043 | mutex_unlock(&ipmi_interfaces_mutex); | 3006 | mutex_unlock(&ipmi_interfaces_mutex); |
3044 | synchronize_rcu(); | 3007 | synchronize_rcu(); |
3045 | 3008 | ||
3046 | cleanup_smi_msgs(intf); | 3009 | cleanup_smi_msgs(intf); |
3047 | 3010 | ||
3011 | /* Clean up the effects of users on the lower-level software. */ | ||
3012 | mutex_lock(&ipmi_interfaces_mutex); | ||
3013 | rcu_read_lock(); | ||
3014 | list_for_each_entry_rcu(user, &intf->users, link) { | ||
3015 | module_put(intf->handlers->owner); | ||
3016 | if (intf->handlers->dec_usecount) | ||
3017 | intf->handlers->dec_usecount(intf->send_info); | ||
3018 | } | ||
3019 | rcu_read_unlock(); | ||
3020 | intf->handlers = NULL; | ||
3021 | mutex_unlock(&ipmi_interfaces_mutex); | ||
3022 | |||
3048 | remove_proc_entries(intf); | 3023 | remove_proc_entries(intf); |
3049 | 3024 | ||
3050 | /* | 3025 | /* |
@@ -3134,7 +3109,6 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
3134 | ipmi_user_t user = NULL; | 3109 | ipmi_user_t user = NULL; |
3135 | struct ipmi_ipmb_addr *ipmb_addr; | 3110 | struct ipmi_ipmb_addr *ipmb_addr; |
3136 | struct ipmi_recv_msg *recv_msg; | 3111 | struct ipmi_recv_msg *recv_msg; |
3137 | struct ipmi_smi_handlers *handlers; | ||
3138 | 3112 | ||
3139 | if (msg->rsp_size < 10) { | 3113 | if (msg->rsp_size < 10) { |
3140 | /* Message not big enough, just ignore it. */ | 3114 | /* Message not big enough, just ignore it. */ |
@@ -3188,9 +3162,8 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, | |||
3188 | } | 3162 | } |
3189 | #endif | 3163 | #endif |
3190 | rcu_read_lock(); | 3164 | rcu_read_lock(); |
3191 | handlers = intf->handlers; | 3165 | if (!intf->in_shutdown) { |
3192 | if (handlers) { | 3166 | smi_send(intf, intf->handlers, msg, 0); |
3193 | handlers->sender(intf->send_info, msg, 0); | ||
3194 | /* | 3167 | /* |
3195 | * We used the message, so return the value | 3168 | * We used the message, so return the value |
3196 | * that causes it to not be freed or | 3169 | * that causes it to not be freed or |
@@ -3857,32 +3830,32 @@ static void handle_new_recv_msgs(ipmi_smi_t intf) | |||
3857 | 3830 | ||
3858 | /* See if any waiting messages need to be processed. */ | 3831 | /* See if any waiting messages need to be processed. */ |
3859 | if (!run_to_completion) | 3832 | if (!run_to_completion) |
3860 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | 3833 | spin_lock_irqsave(&intf->waiting_rcv_msgs_lock, flags); |
3861 | while (!list_empty(&intf->waiting_msgs)) { | 3834 | while (!list_empty(&intf->waiting_rcv_msgs)) { |
3862 | smi_msg = list_entry(intf->waiting_msgs.next, | 3835 | smi_msg = list_entry(intf->waiting_rcv_msgs.next, |
3863 | struct ipmi_smi_msg, link); | 3836 | struct ipmi_smi_msg, link); |
3864 | list_del(&smi_msg->link); | ||
3865 | if (!run_to_completion) | 3837 | if (!run_to_completion) |
3866 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | 3838 | spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock, |
3839 | flags); | ||
3867 | rv = handle_one_recv_msg(intf, smi_msg); | 3840 | rv = handle_one_recv_msg(intf, smi_msg); |
3868 | if (!run_to_completion) | 3841 | if (!run_to_completion) |
3869 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | 3842 | spin_lock_irqsave(&intf->waiting_rcv_msgs_lock, flags); |
3870 | if (rv == 0) { | 3843 | if (rv > 0) { |
3871 | /* Message handled */ | ||
3872 | ipmi_free_smi_msg(smi_msg); | ||
3873 | } else if (rv < 0) { | ||
3874 | /* Fatal error on the message, del but don't free. */ | ||
3875 | } else { | ||
3876 | /* | 3844 | /* |
3877 | * To preserve message order, quit if we | 3845 | * To preserve message order, quit if we |
3878 | * can't handle a message. | 3846 | * can't handle a message. |
3879 | */ | 3847 | */ |
3880 | list_add(&smi_msg->link, &intf->waiting_msgs); | ||
3881 | break; | 3848 | break; |
3849 | } else { | ||
3850 | list_del(&smi_msg->link); | ||
3851 | if (rv == 0) | ||
3852 | /* Message handled */ | ||
3853 | ipmi_free_smi_msg(smi_msg); | ||
3854 | /* If rv < 0, fatal error, del but don't free. */ | ||
3882 | } | 3855 | } |
3883 | } | 3856 | } |
3884 | if (!run_to_completion) | 3857 | if (!run_to_completion) |
3885 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | 3858 | spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock, flags); |
3886 | 3859 | ||
3887 | /* | 3860 | /* |
3888 | * If the pretimout count is non-zero, decrement one from it and | 3861 | * If the pretimout count is non-zero, decrement one from it and |
@@ -3903,7 +3876,41 @@ static void handle_new_recv_msgs(ipmi_smi_t intf) | |||
3903 | 3876 | ||
3904 | static void smi_recv_tasklet(unsigned long val) | 3877 | static void smi_recv_tasklet(unsigned long val) |
3905 | { | 3878 | { |
3906 | handle_new_recv_msgs((ipmi_smi_t) val); | 3879 | unsigned long flags = 0; /* keep us warning-free. */ |
3880 | ipmi_smi_t intf = (ipmi_smi_t) val; | ||
3881 | int run_to_completion = intf->run_to_completion; | ||
3882 | struct ipmi_smi_msg *newmsg = NULL; | ||
3883 | |||
3884 | /* | ||
3885 | * Start the next message if available. | ||
3886 | * | ||
3887 | * Do this here, not in the actual receiver, because we may deadlock | ||
3888 | * because the lower layer is allowed to hold locks while calling | ||
3889 | * message delivery. | ||
3890 | */ | ||
3891 | if (!run_to_completion) | ||
3892 | spin_lock_irqsave(&intf->xmit_msgs_lock, flags); | ||
3893 | if (intf->curr_msg == NULL && !intf->in_shutdown) { | ||
3894 | struct list_head *entry = NULL; | ||
3895 | |||
3896 | /* Pick the high priority queue first. */ | ||
3897 | if (!list_empty(&intf->hp_xmit_msgs)) | ||
3898 | entry = intf->hp_xmit_msgs.next; | ||
3899 | else if (!list_empty(&intf->xmit_msgs)) | ||
3900 | entry = intf->xmit_msgs.next; | ||
3901 | |||
3902 | if (entry) { | ||
3903 | list_del(entry); | ||
3904 | newmsg = list_entry(entry, struct ipmi_smi_msg, link); | ||
3905 | intf->curr_msg = newmsg; | ||
3906 | } | ||
3907 | } | ||
3908 | if (!run_to_completion) | ||
3909 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); | ||
3910 | if (newmsg) | ||
3911 | intf->handlers->sender(intf->send_info, newmsg); | ||
3912 | |||
3913 | handle_new_recv_msgs(intf); | ||
3907 | } | 3914 | } |
3908 | 3915 | ||
3909 | /* Handle a new message from the lower layer. */ | 3916 | /* Handle a new message from the lower layer. */ |
@@ -3911,13 +3918,16 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, | |||
3911 | struct ipmi_smi_msg *msg) | 3918 | struct ipmi_smi_msg *msg) |
3912 | { | 3919 | { |
3913 | unsigned long flags = 0; /* keep us warning-free. */ | 3920 | unsigned long flags = 0; /* keep us warning-free. */ |
3914 | int run_to_completion; | 3921 | int run_to_completion = intf->run_to_completion; |
3915 | |||
3916 | 3922 | ||
3917 | if ((msg->data_size >= 2) | 3923 | if ((msg->data_size >= 2) |
3918 | && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) | 3924 | && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) |
3919 | && (msg->data[1] == IPMI_SEND_MSG_CMD) | 3925 | && (msg->data[1] == IPMI_SEND_MSG_CMD) |
3920 | && (msg->user_data == NULL)) { | 3926 | && (msg->user_data == NULL)) { |
3927 | |||
3928 | if (intf->in_shutdown) | ||
3929 | goto free_msg; | ||
3930 | |||
3921 | /* | 3931 | /* |
3922 | * This is the local response to a command send, start | 3932 | * This is the local response to a command send, start |
3923 | * the timer for these. The user_data will not be | 3933 | * the timer for these. The user_data will not be |
@@ -3953,29 +3963,40 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, | |||
3953 | /* The message was sent, start the timer. */ | 3963 | /* The message was sent, start the timer. */ |
3954 | intf_start_seq_timer(intf, msg->msgid); | 3964 | intf_start_seq_timer(intf, msg->msgid); |
3955 | 3965 | ||
3966 | free_msg: | ||
3956 | ipmi_free_smi_msg(msg); | 3967 | ipmi_free_smi_msg(msg); |
3957 | goto out; | 3968 | } else { |
3969 | /* | ||
3970 | * To preserve message order, we keep a queue and deliver from | ||
3971 | * a tasklet. | ||
3972 | */ | ||
3973 | if (!run_to_completion) | ||
3974 | spin_lock_irqsave(&intf->waiting_rcv_msgs_lock, flags); | ||
3975 | list_add_tail(&msg->link, &intf->waiting_rcv_msgs); | ||
3976 | if (!run_to_completion) | ||
3977 | spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock, | ||
3978 | flags); | ||
3958 | } | 3979 | } |
3959 | 3980 | ||
3960 | /* | ||
3961 | * To preserve message order, if the list is not empty, we | ||
3962 | * tack this message onto the end of the list. | ||
3963 | */ | ||
3964 | run_to_completion = intf->run_to_completion; | ||
3965 | if (!run_to_completion) | 3981 | if (!run_to_completion) |
3966 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | 3982 | spin_lock_irqsave(&intf->xmit_msgs_lock, flags); |
3967 | list_add_tail(&msg->link, &intf->waiting_msgs); | 3983 | if (msg == intf->curr_msg) |
3984 | intf->curr_msg = NULL; | ||
3968 | if (!run_to_completion) | 3985 | if (!run_to_completion) |
3969 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | 3986 | spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags); |
3970 | 3987 | ||
3971 | tasklet_schedule(&intf->recv_tasklet); | 3988 | if (run_to_completion) |
3972 | out: | 3989 | smi_recv_tasklet((unsigned long) intf); |
3973 | return; | 3990 | else |
3991 | tasklet_schedule(&intf->recv_tasklet); | ||
3974 | } | 3992 | } |
3975 | EXPORT_SYMBOL(ipmi_smi_msg_received); | 3993 | EXPORT_SYMBOL(ipmi_smi_msg_received); |
3976 | 3994 | ||
3977 | void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) | 3995 | void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) |
3978 | { | 3996 | { |
3997 | if (intf->in_shutdown) | ||
3998 | return; | ||
3999 | |||
3979 | atomic_set(&intf->watchdog_pretimeouts_to_deliver, 1); | 4000 | atomic_set(&intf->watchdog_pretimeouts_to_deliver, 1); |
3980 | tasklet_schedule(&intf->recv_tasklet); | 4001 | tasklet_schedule(&intf->recv_tasklet); |
3981 | } | 4002 | } |
@@ -4017,7 +4038,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
4017 | struct ipmi_recv_msg *msg; | 4038 | struct ipmi_recv_msg *msg; |
4018 | struct ipmi_smi_handlers *handlers; | 4039 | struct ipmi_smi_handlers *handlers; |
4019 | 4040 | ||
4020 | if (intf->intf_num == -1) | 4041 | if (intf->in_shutdown) |
4021 | return; | 4042 | return; |
4022 | 4043 | ||
4023 | if (!ent->inuse) | 4044 | if (!ent->inuse) |
@@ -4082,8 +4103,7 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, | |||
4082 | ipmi_inc_stat(intf, | 4103 | ipmi_inc_stat(intf, |
4083 | retransmitted_ipmb_commands); | 4104 | retransmitted_ipmb_commands); |
4084 | 4105 | ||
4085 | intf->handlers->sender(intf->send_info, | 4106 | smi_send(intf, intf->handlers, smi_msg, 0); |
4086 | smi_msg, 0); | ||
4087 | } else | 4107 | } else |
4088 | ipmi_free_smi_msg(smi_msg); | 4108 | ipmi_free_smi_msg(smi_msg); |
4089 | 4109 | ||
@@ -4145,15 +4165,12 @@ static unsigned int ipmi_timeout_handler(ipmi_smi_t intf, long timeout_period) | |||
4145 | 4165 | ||
4146 | static void ipmi_request_event(ipmi_smi_t intf) | 4166 | static void ipmi_request_event(ipmi_smi_t intf) |
4147 | { | 4167 | { |
4148 | struct ipmi_smi_handlers *handlers; | ||
4149 | |||
4150 | /* No event requests when in maintenance mode. */ | 4168 | /* No event requests when in maintenance mode. */ |
4151 | if (intf->maintenance_mode_enable) | 4169 | if (intf->maintenance_mode_enable) |
4152 | return; | 4170 | return; |
4153 | 4171 | ||
4154 | handlers = intf->handlers; | 4172 | if (!intf->in_shutdown) |
4155 | if (handlers) | 4173 | intf->handlers->request_events(intf->send_info); |
4156 | handlers->request_events(intf->send_info); | ||
4157 | } | 4174 | } |
4158 | 4175 | ||
4159 | static struct timer_list ipmi_timer; | 4176 | static struct timer_list ipmi_timer; |
@@ -4548,6 +4565,7 @@ static int ipmi_init_msghandler(void) | |||
4548 | proc_ipmi_root = proc_mkdir("ipmi", NULL); | 4565 | proc_ipmi_root = proc_mkdir("ipmi", NULL); |
4549 | if (!proc_ipmi_root) { | 4566 | if (!proc_ipmi_root) { |
4550 | printk(KERN_ERR PFX "Unable to create IPMI proc dir"); | 4567 | printk(KERN_ERR PFX "Unable to create IPMI proc dir"); |
4568 | driver_unregister(&ipmidriver.driver); | ||
4551 | return -ENOMEM; | 4569 | return -ENOMEM; |
4552 | } | 4570 | } |
4553 | 4571 | ||
diff --git a/drivers/char/ipmi/ipmi_powernv.c b/drivers/char/ipmi/ipmi_powernv.c new file mode 100644 index 000000000000..79524ed2a3cb --- /dev/null +++ b/drivers/char/ipmi/ipmi_powernv.c | |||
@@ -0,0 +1,310 @@ | |||
1 | /* | ||
2 | * PowerNV OPAL IPMI driver | ||
3 | * | ||
4 | * Copyright 2014 IBM Corp. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation; either version 2 of the License, or (at your option) | ||
9 | * any later version. | ||
10 | */ | ||
11 | |||
12 | #define pr_fmt(fmt) "ipmi-powernv: " fmt | ||
13 | |||
14 | #include <linux/ipmi_smi.h> | ||
15 | #include <linux/list.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/of.h> | ||
18 | |||
19 | #include <asm/opal.h> | ||
20 | |||
21 | |||
22 | struct ipmi_smi_powernv { | ||
23 | u64 interface_id; | ||
24 | struct ipmi_device_id ipmi_id; | ||
25 | ipmi_smi_t intf; | ||
26 | u64 event; | ||
27 | struct notifier_block event_nb; | ||
28 | |||
29 | /** | ||
30 | * We assume that there can only be one outstanding request, so | ||
31 | * keep the pending message in cur_msg. We protect this from concurrent | ||
32 | * updates through send & recv calls, (and consequently opal_msg, which | ||
33 | * is in-use when cur_msg is set) with msg_lock | ||
34 | */ | ||
35 | spinlock_t msg_lock; | ||
36 | struct ipmi_smi_msg *cur_msg; | ||
37 | struct opal_ipmi_msg *opal_msg; | ||
38 | }; | ||
39 | |||
40 | static int ipmi_powernv_start_processing(void *send_info, ipmi_smi_t intf) | ||
41 | { | ||
42 | struct ipmi_smi_powernv *smi = send_info; | ||
43 | |||
44 | smi->intf = intf; | ||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | static void send_error_reply(struct ipmi_smi_powernv *smi, | ||
49 | struct ipmi_smi_msg *msg, u8 completion_code) | ||
50 | { | ||
51 | msg->rsp[0] = msg->data[0] | 0x4; | ||
52 | msg->rsp[1] = msg->data[1]; | ||
53 | msg->rsp[2] = completion_code; | ||
54 | msg->rsp_size = 3; | ||
55 | ipmi_smi_msg_received(smi->intf, msg); | ||
56 | } | ||
57 | |||
58 | static void ipmi_powernv_send(void *send_info, struct ipmi_smi_msg *msg) | ||
59 | { | ||
60 | struct ipmi_smi_powernv *smi = send_info; | ||
61 | struct opal_ipmi_msg *opal_msg; | ||
62 | unsigned long flags; | ||
63 | int comp, rc; | ||
64 | size_t size; | ||
65 | |||
66 | /* ensure data_len will fit in the opal_ipmi_msg buffer... */ | ||
67 | if (msg->data_size > IPMI_MAX_MSG_LENGTH) { | ||
68 | comp = IPMI_REQ_LEN_EXCEEDED_ERR; | ||
69 | goto err; | ||
70 | } | ||
71 | |||
72 | /* ... and that we at least have netfn and cmd bytes */ | ||
73 | if (msg->data_size < 2) { | ||
74 | comp = IPMI_REQ_LEN_INVALID_ERR; | ||
75 | goto err; | ||
76 | } | ||
77 | |||
78 | spin_lock_irqsave(&smi->msg_lock, flags); | ||
79 | |||
80 | if (smi->cur_msg) { | ||
81 | comp = IPMI_NODE_BUSY_ERR; | ||
82 | goto err_unlock; | ||
83 | } | ||
84 | |||
85 | /* format our data for the OPAL API */ | ||
86 | opal_msg = smi->opal_msg; | ||
87 | opal_msg->version = OPAL_IPMI_MSG_FORMAT_VERSION_1; | ||
88 | opal_msg->netfn = msg->data[0]; | ||
89 | opal_msg->cmd = msg->data[1]; | ||
90 | if (msg->data_size > 2) | ||
91 | memcpy(opal_msg->data, msg->data + 2, msg->data_size - 2); | ||
92 | |||
93 | /* data_size already includes the netfn and cmd bytes */ | ||
94 | size = sizeof(*opal_msg) + msg->data_size - 2; | ||
95 | |||
96 | pr_devel("%s: opal_ipmi_send(0x%llx, %p, %ld)\n", __func__, | ||
97 | smi->interface_id, opal_msg, size); | ||
98 | rc = opal_ipmi_send(smi->interface_id, opal_msg, size); | ||
99 | pr_devel("%s: -> %d\n", __func__, rc); | ||
100 | |||
101 | if (!rc) { | ||
102 | smi->cur_msg = msg; | ||
103 | spin_unlock_irqrestore(&smi->msg_lock, flags); | ||
104 | return; | ||
105 | } | ||
106 | |||
107 | comp = IPMI_ERR_UNSPECIFIED; | ||
108 | err_unlock: | ||
109 | spin_unlock_irqrestore(&smi->msg_lock, flags); | ||
110 | err: | ||
111 | send_error_reply(smi, msg, comp); | ||
112 | } | ||
113 | |||
114 | static int ipmi_powernv_recv(struct ipmi_smi_powernv *smi) | ||
115 | { | ||
116 | struct opal_ipmi_msg *opal_msg; | ||
117 | struct ipmi_smi_msg *msg; | ||
118 | unsigned long flags; | ||
119 | uint64_t size; | ||
120 | int rc; | ||
121 | |||
122 | pr_devel("%s: opal_ipmi_recv(%llx, msg, sz)\n", __func__, | ||
123 | smi->interface_id); | ||
124 | |||
125 | spin_lock_irqsave(&smi->msg_lock, flags); | ||
126 | |||
127 | if (!smi->cur_msg) { | ||
128 | pr_warn("no current message?\n"); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | msg = smi->cur_msg; | ||
133 | opal_msg = smi->opal_msg; | ||
134 | |||
135 | size = cpu_to_be64(sizeof(*opal_msg) + IPMI_MAX_MSG_LENGTH); | ||
136 | |||
137 | rc = opal_ipmi_recv(smi->interface_id, | ||
138 | opal_msg, | ||
139 | &size); | ||
140 | size = be64_to_cpu(size); | ||
141 | pr_devel("%s: -> %d (size %lld)\n", __func__, | ||
142 | rc, rc == 0 ? size : 0); | ||
143 | if (rc) { | ||
144 | spin_unlock_irqrestore(&smi->msg_lock, flags); | ||
145 | ipmi_free_smi_msg(msg); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | if (size < sizeof(*opal_msg)) { | ||
150 | spin_unlock_irqrestore(&smi->msg_lock, flags); | ||
151 | pr_warn("unexpected IPMI message size %lld\n", size); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | if (opal_msg->version != OPAL_IPMI_MSG_FORMAT_VERSION_1) { | ||
156 | spin_unlock_irqrestore(&smi->msg_lock, flags); | ||
157 | pr_warn("unexpected IPMI message format (version %d)\n", | ||
158 | opal_msg->version); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | msg->rsp[0] = opal_msg->netfn; | ||
163 | msg->rsp[1] = opal_msg->cmd; | ||
164 | if (size > sizeof(*opal_msg)) | ||
165 | memcpy(&msg->rsp[2], opal_msg->data, size - sizeof(*opal_msg)); | ||
166 | msg->rsp_size = 2 + size - sizeof(*opal_msg); | ||
167 | |||
168 | smi->cur_msg = NULL; | ||
169 | spin_unlock_irqrestore(&smi->msg_lock, flags); | ||
170 | ipmi_smi_msg_received(smi->intf, msg); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void ipmi_powernv_request_events(void *send_info) | ||
175 | { | ||
176 | } | ||
177 | |||
178 | static void ipmi_powernv_set_run_to_completion(void *send_info, | ||
179 | bool run_to_completion) | ||
180 | { | ||
181 | } | ||
182 | |||
183 | static void ipmi_powernv_poll(void *send_info) | ||
184 | { | ||
185 | struct ipmi_smi_powernv *smi = send_info; | ||
186 | |||
187 | ipmi_powernv_recv(smi); | ||
188 | } | ||
189 | |||
190 | static struct ipmi_smi_handlers ipmi_powernv_smi_handlers = { | ||
191 | .owner = THIS_MODULE, | ||
192 | .start_processing = ipmi_powernv_start_processing, | ||
193 | .sender = ipmi_powernv_send, | ||
194 | .request_events = ipmi_powernv_request_events, | ||
195 | .set_run_to_completion = ipmi_powernv_set_run_to_completion, | ||
196 | .poll = ipmi_powernv_poll, | ||
197 | }; | ||
198 | |||
199 | static int ipmi_opal_event(struct notifier_block *nb, | ||
200 | unsigned long events, void *change) | ||
201 | { | ||
202 | struct ipmi_smi_powernv *smi = container_of(nb, | ||
203 | struct ipmi_smi_powernv, event_nb); | ||
204 | |||
205 | if (events & smi->event) | ||
206 | ipmi_powernv_recv(smi); | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int ipmi_powernv_probe(struct platform_device *pdev) | ||
211 | { | ||
212 | struct ipmi_smi_powernv *ipmi; | ||
213 | struct device *dev; | ||
214 | u32 prop; | ||
215 | int rc; | ||
216 | |||
217 | if (!pdev || !pdev->dev.of_node) | ||
218 | return -ENODEV; | ||
219 | |||
220 | dev = &pdev->dev; | ||
221 | |||
222 | ipmi = devm_kzalloc(dev, sizeof(*ipmi), GFP_KERNEL); | ||
223 | if (!ipmi) | ||
224 | return -ENOMEM; | ||
225 | |||
226 | spin_lock_init(&ipmi->msg_lock); | ||
227 | |||
228 | rc = of_property_read_u32(dev->of_node, "ibm,ipmi-interface-id", | ||
229 | &prop); | ||
230 | if (rc) { | ||
231 | dev_warn(dev, "No interface ID property\n"); | ||
232 | goto err_free; | ||
233 | } | ||
234 | ipmi->interface_id = prop; | ||
235 | |||
236 | rc = of_property_read_u32(dev->of_node, "interrupts", &prop); | ||
237 | if (rc) { | ||
238 | dev_warn(dev, "No interrupts property\n"); | ||
239 | goto err_free; | ||
240 | } | ||
241 | |||
242 | ipmi->event = 1ull << prop; | ||
243 | ipmi->event_nb.notifier_call = ipmi_opal_event; | ||
244 | |||
245 | rc = opal_notifier_register(&ipmi->event_nb); | ||
246 | if (rc) { | ||
247 | dev_warn(dev, "OPAL notifier registration failed (%d)\n", rc); | ||
248 | goto err_free; | ||
249 | } | ||
250 | |||
251 | ipmi->opal_msg = devm_kmalloc(dev, | ||
252 | sizeof(*ipmi->opal_msg) + IPMI_MAX_MSG_LENGTH, | ||
253 | GFP_KERNEL); | ||
254 | if (!ipmi->opal_msg) { | ||
255 | rc = -ENOMEM; | ||
256 | goto err_unregister; | ||
257 | } | ||
258 | |||
259 | /* todo: query actual ipmi_device_id */ | ||
260 | rc = ipmi_register_smi(&ipmi_powernv_smi_handlers, ipmi, | ||
261 | &ipmi->ipmi_id, dev, 0); | ||
262 | if (rc) { | ||
263 | dev_warn(dev, "IPMI SMI registration failed (%d)\n", rc); | ||
264 | goto err_free_msg; | ||
265 | } | ||
266 | |||
267 | dev_set_drvdata(dev, ipmi); | ||
268 | return 0; | ||
269 | |||
270 | err_free_msg: | ||
271 | devm_kfree(dev, ipmi->opal_msg); | ||
272 | err_unregister: | ||
273 | opal_notifier_unregister(&ipmi->event_nb); | ||
274 | err_free: | ||
275 | devm_kfree(dev, ipmi); | ||
276 | return rc; | ||
277 | } | ||
278 | |||
279 | static int ipmi_powernv_remove(struct platform_device *pdev) | ||
280 | { | ||
281 | struct ipmi_smi_powernv *smi = dev_get_drvdata(&pdev->dev); | ||
282 | |||
283 | ipmi_unregister_smi(smi->intf); | ||
284 | opal_notifier_unregister(&smi->event_nb); | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static const struct of_device_id ipmi_powernv_match[] = { | ||
289 | { .compatible = "ibm,opal-ipmi" }, | ||
290 | { }, | ||
291 | }; | ||
292 | |||
293 | |||
294 | static struct platform_driver powernv_ipmi_driver = { | ||
295 | .driver = { | ||
296 | .name = "ipmi-powernv", | ||
297 | .owner = THIS_MODULE, | ||
298 | .of_match_table = ipmi_powernv_match, | ||
299 | }, | ||
300 | .probe = ipmi_powernv_probe, | ||
301 | .remove = ipmi_powernv_remove, | ||
302 | }; | ||
303 | |||
304 | |||
305 | module_platform_driver(powernv_ipmi_driver); | ||
306 | |||
307 | MODULE_DEVICE_TABLE(of, ipmi_powernv_match); | ||
308 | MODULE_DESCRIPTION("powernv IPMI driver"); | ||
309 | MODULE_AUTHOR("Jeremy Kerr <jk@ozlabs.org>"); | ||
310 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 5c4e1f625bbb..90c7fdf95419 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -92,12 +92,9 @@ enum si_intf_state { | |||
92 | SI_GETTING_FLAGS, | 92 | SI_GETTING_FLAGS, |
93 | SI_GETTING_EVENTS, | 93 | SI_GETTING_EVENTS, |
94 | SI_CLEARING_FLAGS, | 94 | SI_CLEARING_FLAGS, |
95 | SI_CLEARING_FLAGS_THEN_SET_IRQ, | ||
96 | SI_GETTING_MESSAGES, | 95 | SI_GETTING_MESSAGES, |
97 | SI_ENABLE_INTERRUPTS1, | 96 | SI_CHECKING_ENABLES, |
98 | SI_ENABLE_INTERRUPTS2, | 97 | SI_SETTING_ENABLES |
99 | SI_DISABLE_INTERRUPTS1, | ||
100 | SI_DISABLE_INTERRUPTS2 | ||
101 | /* FIXME - add watchdog stuff. */ | 98 | /* FIXME - add watchdog stuff. */ |
102 | }; | 99 | }; |
103 | 100 | ||
@@ -111,10 +108,6 @@ enum si_type { | |||
111 | }; | 108 | }; |
112 | static char *si_to_str[] = { "kcs", "smic", "bt" }; | 109 | static char *si_to_str[] = { "kcs", "smic", "bt" }; |
113 | 110 | ||
114 | static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI", | ||
115 | "ACPI", "SMBIOS", "PCI", | ||
116 | "device-tree", "default" }; | ||
117 | |||
118 | #define DEVICE_NAME "ipmi_si" | 111 | #define DEVICE_NAME "ipmi_si" |
119 | 112 | ||
120 | static struct platform_driver ipmi_driver; | 113 | static struct platform_driver ipmi_driver; |
@@ -174,8 +167,7 @@ struct smi_info { | |||
174 | struct si_sm_handlers *handlers; | 167 | struct si_sm_handlers *handlers; |
175 | enum si_type si_type; | 168 | enum si_type si_type; |
176 | spinlock_t si_lock; | 169 | spinlock_t si_lock; |
177 | struct list_head xmit_msgs; | 170 | struct ipmi_smi_msg *waiting_msg; |
178 | struct list_head hp_xmit_msgs; | ||
179 | struct ipmi_smi_msg *curr_msg; | 171 | struct ipmi_smi_msg *curr_msg; |
180 | enum si_intf_state si_state; | 172 | enum si_intf_state si_state; |
181 | 173 | ||
@@ -254,9 +246,6 @@ struct smi_info { | |||
254 | /* The time (in jiffies) the last timeout occurred at. */ | 246 | /* The time (in jiffies) the last timeout occurred at. */ |
255 | unsigned long last_timeout_jiffies; | 247 | unsigned long last_timeout_jiffies; |
256 | 248 | ||
257 | /* Used to gracefully stop the timer without race conditions. */ | ||
258 | atomic_t stop_operation; | ||
259 | |||
260 | /* Are we waiting for the events, pretimeouts, received msgs? */ | 249 | /* Are we waiting for the events, pretimeouts, received msgs? */ |
261 | atomic_t need_watch; | 250 | atomic_t need_watch; |
262 | 251 | ||
@@ -268,6 +257,16 @@ struct smi_info { | |||
268 | */ | 257 | */ |
269 | bool interrupt_disabled; | 258 | bool interrupt_disabled; |
270 | 259 | ||
260 | /* | ||
261 | * Does the BMC support events? | ||
262 | */ | ||
263 | bool supports_event_msg_buff; | ||
264 | |||
265 | /* | ||
266 | * Did we get an attention that we did not handle? | ||
267 | */ | ||
268 | bool got_attn; | ||
269 | |||
271 | /* From the get device id response... */ | 270 | /* From the get device id response... */ |
272 | struct ipmi_device_id device_id; | 271 | struct ipmi_device_id device_id; |
273 | 272 | ||
@@ -332,7 +331,10 @@ static void deliver_recv_msg(struct smi_info *smi_info, | |||
332 | struct ipmi_smi_msg *msg) | 331 | struct ipmi_smi_msg *msg) |
333 | { | 332 | { |
334 | /* Deliver the message to the upper layer. */ | 333 | /* Deliver the message to the upper layer. */ |
335 | ipmi_smi_msg_received(smi_info->intf, msg); | 334 | if (smi_info->intf) |
335 | ipmi_smi_msg_received(smi_info->intf, msg); | ||
336 | else | ||
337 | ipmi_free_smi_msg(msg); | ||
336 | } | 338 | } |
337 | 339 | ||
338 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) | 340 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) |
@@ -356,28 +358,18 @@ static void return_hosed_msg(struct smi_info *smi_info, int cCode) | |||
356 | static enum si_sm_result start_next_msg(struct smi_info *smi_info) | 358 | static enum si_sm_result start_next_msg(struct smi_info *smi_info) |
357 | { | 359 | { |
358 | int rv; | 360 | int rv; |
359 | struct list_head *entry = NULL; | ||
360 | #ifdef DEBUG_TIMING | 361 | #ifdef DEBUG_TIMING |
361 | struct timeval t; | 362 | struct timeval t; |
362 | #endif | 363 | #endif |
363 | 364 | ||
364 | /* Pick the high priority queue first. */ | 365 | if (!smi_info->waiting_msg) { |
365 | if (!list_empty(&(smi_info->hp_xmit_msgs))) { | ||
366 | entry = smi_info->hp_xmit_msgs.next; | ||
367 | } else if (!list_empty(&(smi_info->xmit_msgs))) { | ||
368 | entry = smi_info->xmit_msgs.next; | ||
369 | } | ||
370 | |||
371 | if (!entry) { | ||
372 | smi_info->curr_msg = NULL; | 366 | smi_info->curr_msg = NULL; |
373 | rv = SI_SM_IDLE; | 367 | rv = SI_SM_IDLE; |
374 | } else { | 368 | } else { |
375 | int err; | 369 | int err; |
376 | 370 | ||
377 | list_del(entry); | 371 | smi_info->curr_msg = smi_info->waiting_msg; |
378 | smi_info->curr_msg = list_entry(entry, | 372 | smi_info->waiting_msg = NULL; |
379 | struct ipmi_smi_msg, | ||
380 | link); | ||
381 | #ifdef DEBUG_TIMING | 373 | #ifdef DEBUG_TIMING |
382 | do_gettimeofday(&t); | 374 | do_gettimeofday(&t); |
383 | printk(KERN_DEBUG "**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 375 | printk(KERN_DEBUG "**Start2: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
@@ -401,30 +393,15 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
401 | return rv; | 393 | return rv; |
402 | } | 394 | } |
403 | 395 | ||
404 | static void start_enable_irq(struct smi_info *smi_info) | 396 | static void start_check_enables(struct smi_info *smi_info) |
405 | { | 397 | { |
406 | unsigned char msg[2]; | 398 | unsigned char msg[2]; |
407 | 399 | ||
408 | /* | ||
409 | * If we are enabling interrupts, we have to tell the | ||
410 | * BMC to use them. | ||
411 | */ | ||
412 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 400 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |
413 | msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; | 401 | msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; |
414 | 402 | ||
415 | smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); | 403 | smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); |
416 | smi_info->si_state = SI_ENABLE_INTERRUPTS1; | 404 | smi_info->si_state = SI_CHECKING_ENABLES; |
417 | } | ||
418 | |||
419 | static void start_disable_irq(struct smi_info *smi_info) | ||
420 | { | ||
421 | unsigned char msg[2]; | ||
422 | |||
423 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
424 | msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; | ||
425 | |||
426 | smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2); | ||
427 | smi_info->si_state = SI_DISABLE_INTERRUPTS1; | ||
428 | } | 405 | } |
429 | 406 | ||
430 | static void start_clear_flags(struct smi_info *smi_info) | 407 | static void start_clear_flags(struct smi_info *smi_info) |
@@ -440,6 +417,32 @@ static void start_clear_flags(struct smi_info *smi_info) | |||
440 | smi_info->si_state = SI_CLEARING_FLAGS; | 417 | smi_info->si_state = SI_CLEARING_FLAGS; |
441 | } | 418 | } |
442 | 419 | ||
420 | static void start_getting_msg_queue(struct smi_info *smi_info) | ||
421 | { | ||
422 | smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
423 | smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD; | ||
424 | smi_info->curr_msg->data_size = 2; | ||
425 | |||
426 | smi_info->handlers->start_transaction( | ||
427 | smi_info->si_sm, | ||
428 | smi_info->curr_msg->data, | ||
429 | smi_info->curr_msg->data_size); | ||
430 | smi_info->si_state = SI_GETTING_MESSAGES; | ||
431 | } | ||
432 | |||
433 | static void start_getting_events(struct smi_info *smi_info) | ||
434 | { | ||
435 | smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
436 | smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD; | ||
437 | smi_info->curr_msg->data_size = 2; | ||
438 | |||
439 | smi_info->handlers->start_transaction( | ||
440 | smi_info->si_sm, | ||
441 | smi_info->curr_msg->data, | ||
442 | smi_info->curr_msg->data_size); | ||
443 | smi_info->si_state = SI_GETTING_EVENTS; | ||
444 | } | ||
445 | |||
443 | static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val) | 446 | static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val) |
444 | { | 447 | { |
445 | smi_info->last_timeout_jiffies = jiffies; | 448 | smi_info->last_timeout_jiffies = jiffies; |
@@ -453,22 +456,45 @@ static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val) | |||
453 | * polled until we can allocate some memory. Once we have some | 456 | * polled until we can allocate some memory. Once we have some |
454 | * memory, we will re-enable the interrupt. | 457 | * memory, we will re-enable the interrupt. |
455 | */ | 458 | */ |
456 | static inline void disable_si_irq(struct smi_info *smi_info) | 459 | static inline bool disable_si_irq(struct smi_info *smi_info) |
457 | { | 460 | { |
458 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 461 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
459 | start_disable_irq(smi_info); | ||
460 | smi_info->interrupt_disabled = true; | 462 | smi_info->interrupt_disabled = true; |
461 | if (!atomic_read(&smi_info->stop_operation)) | 463 | start_check_enables(smi_info); |
462 | smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); | 464 | return true; |
463 | } | 465 | } |
466 | return false; | ||
464 | } | 467 | } |
465 | 468 | ||
466 | static inline void enable_si_irq(struct smi_info *smi_info) | 469 | static inline bool enable_si_irq(struct smi_info *smi_info) |
467 | { | 470 | { |
468 | if ((smi_info->irq) && (smi_info->interrupt_disabled)) { | 471 | if ((smi_info->irq) && (smi_info->interrupt_disabled)) { |
469 | start_enable_irq(smi_info); | ||
470 | smi_info->interrupt_disabled = false; | 472 | smi_info->interrupt_disabled = false; |
473 | start_check_enables(smi_info); | ||
474 | return true; | ||
471 | } | 475 | } |
476 | return false; | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * Allocate a message. If unable to allocate, start the interrupt | ||
481 | * disable process and return NULL. If able to allocate but | ||
482 | * interrupts are disabled, free the message and return NULL after | ||
483 | * starting the interrupt enable process. | ||
484 | */ | ||
485 | static struct ipmi_smi_msg *alloc_msg_handle_irq(struct smi_info *smi_info) | ||
486 | { | ||
487 | struct ipmi_smi_msg *msg; | ||
488 | |||
489 | msg = ipmi_alloc_smi_msg(); | ||
490 | if (!msg) { | ||
491 | if (!disable_si_irq(smi_info)) | ||
492 | smi_info->si_state = SI_NORMAL; | ||
493 | } else if (enable_si_irq(smi_info)) { | ||
494 | ipmi_free_smi_msg(msg); | ||
495 | msg = NULL; | ||
496 | } | ||
497 | return msg; | ||
472 | } | 498 | } |
473 | 499 | ||
474 | static void handle_flags(struct smi_info *smi_info) | 500 | static void handle_flags(struct smi_info *smi_info) |
@@ -480,45 +506,22 @@ static void handle_flags(struct smi_info *smi_info) | |||
480 | 506 | ||
481 | start_clear_flags(smi_info); | 507 | start_clear_flags(smi_info); |
482 | smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; | 508 | smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; |
483 | ipmi_smi_watchdog_pretimeout(smi_info->intf); | 509 | if (smi_info->intf) |
510 | ipmi_smi_watchdog_pretimeout(smi_info->intf); | ||
484 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { | 511 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { |
485 | /* Messages available. */ | 512 | /* Messages available. */ |
486 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 513 | smi_info->curr_msg = alloc_msg_handle_irq(smi_info); |
487 | if (!smi_info->curr_msg) { | 514 | if (!smi_info->curr_msg) |
488 | disable_si_irq(smi_info); | ||
489 | smi_info->si_state = SI_NORMAL; | ||
490 | return; | 515 | return; |
491 | } | ||
492 | enable_si_irq(smi_info); | ||
493 | |||
494 | smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
495 | smi_info->curr_msg->data[1] = IPMI_GET_MSG_CMD; | ||
496 | smi_info->curr_msg->data_size = 2; | ||
497 | 516 | ||
498 | smi_info->handlers->start_transaction( | 517 | start_getting_msg_queue(smi_info); |
499 | smi_info->si_sm, | ||
500 | smi_info->curr_msg->data, | ||
501 | smi_info->curr_msg->data_size); | ||
502 | smi_info->si_state = SI_GETTING_MESSAGES; | ||
503 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { | 518 | } else if (smi_info->msg_flags & EVENT_MSG_BUFFER_FULL) { |
504 | /* Events available. */ | 519 | /* Events available. */ |
505 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 520 | smi_info->curr_msg = alloc_msg_handle_irq(smi_info); |
506 | if (!smi_info->curr_msg) { | 521 | if (!smi_info->curr_msg) |
507 | disable_si_irq(smi_info); | ||
508 | smi_info->si_state = SI_NORMAL; | ||
509 | return; | 522 | return; |
510 | } | ||
511 | enable_si_irq(smi_info); | ||
512 | |||
513 | smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
514 | smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD; | ||
515 | smi_info->curr_msg->data_size = 2; | ||
516 | 523 | ||
517 | smi_info->handlers->start_transaction( | 524 | start_getting_events(smi_info); |
518 | smi_info->si_sm, | ||
519 | smi_info->curr_msg->data, | ||
520 | smi_info->curr_msg->data_size); | ||
521 | smi_info->si_state = SI_GETTING_EVENTS; | ||
522 | } else if (smi_info->msg_flags & OEM_DATA_AVAIL && | 525 | } else if (smi_info->msg_flags & OEM_DATA_AVAIL && |
523 | smi_info->oem_data_avail_handler) { | 526 | smi_info->oem_data_avail_handler) { |
524 | if (smi_info->oem_data_avail_handler(smi_info)) | 527 | if (smi_info->oem_data_avail_handler(smi_info)) |
@@ -527,6 +530,55 @@ static void handle_flags(struct smi_info *smi_info) | |||
527 | smi_info->si_state = SI_NORMAL; | 530 | smi_info->si_state = SI_NORMAL; |
528 | } | 531 | } |
529 | 532 | ||
533 | /* | ||
534 | * Global enables we care about. | ||
535 | */ | ||
536 | #define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR | \ | ||
537 | IPMI_BMC_EVT_MSG_INTR) | ||
538 | |||
539 | static u8 current_global_enables(struct smi_info *smi_info, u8 base, | ||
540 | bool *irq_on) | ||
541 | { | ||
542 | u8 enables = 0; | ||
543 | |||
544 | if (smi_info->supports_event_msg_buff) | ||
545 | enables |= IPMI_BMC_EVT_MSG_BUFF; | ||
546 | else | ||
547 | enables &= ~IPMI_BMC_EVT_MSG_BUFF; | ||
548 | |||
549 | if (smi_info->irq && !smi_info->interrupt_disabled) | ||
550 | enables |= IPMI_BMC_RCV_MSG_INTR; | ||
551 | else | ||
552 | enables &= ~IPMI_BMC_RCV_MSG_INTR; | ||
553 | |||
554 | if (smi_info->supports_event_msg_buff && | ||
555 | smi_info->irq && !smi_info->interrupt_disabled) | ||
556 | |||
557 | enables |= IPMI_BMC_EVT_MSG_INTR; | ||
558 | else | ||
559 | enables &= ~IPMI_BMC_EVT_MSG_INTR; | ||
560 | |||
561 | *irq_on = enables & (IPMI_BMC_EVT_MSG_INTR | IPMI_BMC_RCV_MSG_INTR); | ||
562 | |||
563 | return enables; | ||
564 | } | ||
565 | |||
566 | static void check_bt_irq(struct smi_info *smi_info, bool irq_on) | ||
567 | { | ||
568 | u8 irqstate = smi_info->io.inputb(&smi_info->io, IPMI_BT_INTMASK_REG); | ||
569 | |||
570 | irqstate &= IPMI_BT_INTMASK_ENABLE_IRQ_BIT; | ||
571 | |||
572 | if ((bool)irqstate == irq_on) | ||
573 | return; | ||
574 | |||
575 | if (irq_on) | ||
576 | smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG, | ||
577 | IPMI_BT_INTMASK_ENABLE_IRQ_BIT); | ||
578 | else | ||
579 | smi_info->io.outputb(&smi_info->io, IPMI_BT_INTMASK_REG, 0); | ||
580 | } | ||
581 | |||
530 | static void handle_transaction_done(struct smi_info *smi_info) | 582 | static void handle_transaction_done(struct smi_info *smi_info) |
531 | { | 583 | { |
532 | struct ipmi_smi_msg *msg; | 584 | struct ipmi_smi_msg *msg; |
@@ -581,7 +633,6 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
581 | } | 633 | } |
582 | 634 | ||
583 | case SI_CLEARING_FLAGS: | 635 | case SI_CLEARING_FLAGS: |
584 | case SI_CLEARING_FLAGS_THEN_SET_IRQ: | ||
585 | { | 636 | { |
586 | unsigned char msg[3]; | 637 | unsigned char msg[3]; |
587 | 638 | ||
@@ -592,10 +643,7 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
592 | dev_warn(smi_info->dev, | 643 | dev_warn(smi_info->dev, |
593 | "Error clearing flags: %2.2x\n", msg[2]); | 644 | "Error clearing flags: %2.2x\n", msg[2]); |
594 | } | 645 | } |
595 | if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ) | 646 | smi_info->si_state = SI_NORMAL; |
596 | start_enable_irq(smi_info); | ||
597 | else | ||
598 | smi_info->si_state = SI_NORMAL; | ||
599 | break; | 647 | break; |
600 | } | 648 | } |
601 | 649 | ||
@@ -675,9 +723,11 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
675 | break; | 723 | break; |
676 | } | 724 | } |
677 | 725 | ||
678 | case SI_ENABLE_INTERRUPTS1: | 726 | case SI_CHECKING_ENABLES: |
679 | { | 727 | { |
680 | unsigned char msg[4]; | 728 | unsigned char msg[4]; |
729 | u8 enables; | ||
730 | bool irq_on; | ||
681 | 731 | ||
682 | /* We got the flags from the SMI, now handle them. */ | 732 | /* We got the flags from the SMI, now handle them. */ |
683 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 733 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
@@ -687,70 +737,53 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
687 | dev_warn(smi_info->dev, | 737 | dev_warn(smi_info->dev, |
688 | "Maybe ok, but ipmi might run very slowly.\n"); | 738 | "Maybe ok, but ipmi might run very slowly.\n"); |
689 | smi_info->si_state = SI_NORMAL; | 739 | smi_info->si_state = SI_NORMAL; |
690 | } else { | 740 | break; |
741 | } | ||
742 | enables = current_global_enables(smi_info, 0, &irq_on); | ||
743 | if (smi_info->si_type == SI_BT) | ||
744 | /* BT has its own interrupt enable bit. */ | ||
745 | check_bt_irq(smi_info, irq_on); | ||
746 | if (enables != (msg[3] & GLOBAL_ENABLES_MASK)) { | ||
747 | /* Enables are not correct, fix them. */ | ||
691 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 748 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |
692 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; | 749 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; |
693 | msg[2] = (msg[3] | | 750 | msg[2] = enables | (msg[3] & ~GLOBAL_ENABLES_MASK); |
694 | IPMI_BMC_RCV_MSG_INTR | | ||
695 | IPMI_BMC_EVT_MSG_INTR); | ||
696 | smi_info->handlers->start_transaction( | 751 | smi_info->handlers->start_transaction( |
697 | smi_info->si_sm, msg, 3); | 752 | smi_info->si_sm, msg, 3); |
698 | smi_info->si_state = SI_ENABLE_INTERRUPTS2; | 753 | smi_info->si_state = SI_SETTING_ENABLES; |
754 | } else if (smi_info->supports_event_msg_buff) { | ||
755 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | ||
756 | if (!smi_info->curr_msg) { | ||
757 | smi_info->si_state = SI_NORMAL; | ||
758 | break; | ||
759 | } | ||
760 | start_getting_msg_queue(smi_info); | ||
761 | } else { | ||
762 | smi_info->si_state = SI_NORMAL; | ||
699 | } | 763 | } |
700 | break; | 764 | break; |
701 | } | 765 | } |
702 | 766 | ||
703 | case SI_ENABLE_INTERRUPTS2: | 767 | case SI_SETTING_ENABLES: |
704 | { | 768 | { |
705 | unsigned char msg[4]; | 769 | unsigned char msg[4]; |
706 | 770 | ||
707 | /* We got the flags from the SMI, now handle them. */ | ||
708 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 771 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
709 | if (msg[2] != 0) { | 772 | if (msg[2] != 0) |
710 | dev_warn(smi_info->dev, | 773 | dev_warn(smi_info->dev, |
711 | "Couldn't set irq info: %x.\n", msg[2]); | 774 | "Could not set the global enables: 0x%x.\n", |
712 | dev_warn(smi_info->dev, | 775 | msg[2]); |
713 | "Maybe ok, but ipmi might run very slowly.\n"); | ||
714 | } else | ||
715 | smi_info->interrupt_disabled = false; | ||
716 | smi_info->si_state = SI_NORMAL; | ||
717 | break; | ||
718 | } | ||
719 | |||
720 | case SI_DISABLE_INTERRUPTS1: | ||
721 | { | ||
722 | unsigned char msg[4]; | ||
723 | 776 | ||
724 | /* We got the flags from the SMI, now handle them. */ | 777 | if (smi_info->supports_event_msg_buff) { |
725 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 778 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
726 | if (msg[2] != 0) { | 779 | if (!smi_info->curr_msg) { |
727 | dev_warn(smi_info->dev, "Could not disable interrupts" | 780 | smi_info->si_state = SI_NORMAL; |
728 | ", failed get.\n"); | 781 | break; |
729 | smi_info->si_state = SI_NORMAL; | 782 | } |
783 | start_getting_msg_queue(smi_info); | ||
730 | } else { | 784 | } else { |
731 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 785 | smi_info->si_state = SI_NORMAL; |
732 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; | ||
733 | msg[2] = (msg[3] & | ||
734 | ~(IPMI_BMC_RCV_MSG_INTR | | ||
735 | IPMI_BMC_EVT_MSG_INTR)); | ||
736 | smi_info->handlers->start_transaction( | ||
737 | smi_info->si_sm, msg, 3); | ||
738 | smi_info->si_state = SI_DISABLE_INTERRUPTS2; | ||
739 | } | ||
740 | break; | ||
741 | } | ||
742 | |||
743 | case SI_DISABLE_INTERRUPTS2: | ||
744 | { | ||
745 | unsigned char msg[4]; | ||
746 | |||
747 | /* We got the flags from the SMI, now handle them. */ | ||
748 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | ||
749 | if (msg[2] != 0) { | ||
750 | dev_warn(smi_info->dev, "Could not disable interrupts" | ||
751 | ", failed set.\n"); | ||
752 | } | 786 | } |
753 | smi_info->si_state = SI_NORMAL; | ||
754 | break; | 787 | break; |
755 | } | 788 | } |
756 | } | 789 | } |
@@ -808,25 +841,35 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, | |||
808 | * We prefer handling attn over new messages. But don't do | 841 | * We prefer handling attn over new messages. But don't do |
809 | * this if there is not yet an upper layer to handle anything. | 842 | * this if there is not yet an upper layer to handle anything. |
810 | */ | 843 | */ |
811 | if (likely(smi_info->intf) && si_sm_result == SI_SM_ATTN) { | 844 | if (likely(smi_info->intf) && |
845 | (si_sm_result == SI_SM_ATTN || smi_info->got_attn)) { | ||
812 | unsigned char msg[2]; | 846 | unsigned char msg[2]; |
813 | 847 | ||
814 | smi_inc_stat(smi_info, attentions); | 848 | if (smi_info->si_state != SI_NORMAL) { |
849 | /* | ||
850 | * We got an ATTN, but we are doing something else. | ||
851 | * Handle the ATTN later. | ||
852 | */ | ||
853 | smi_info->got_attn = true; | ||
854 | } else { | ||
855 | smi_info->got_attn = false; | ||
856 | smi_inc_stat(smi_info, attentions); | ||
815 | 857 | ||
816 | /* | 858 | /* |
817 | * Got a attn, send down a get message flags to see | 859 | * Got a attn, send down a get message flags to see |
818 | * what's causing it. It would be better to handle | 860 | * what's causing it. It would be better to handle |
819 | * this in the upper layer, but due to the way | 861 | * this in the upper layer, but due to the way |
820 | * interrupts work with the SMI, that's not really | 862 | * interrupts work with the SMI, that's not really |
821 | * possible. | 863 | * possible. |
822 | */ | 864 | */ |
823 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 865 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |
824 | msg[1] = IPMI_GET_MSG_FLAGS_CMD; | 866 | msg[1] = IPMI_GET_MSG_FLAGS_CMD; |
825 | 867 | ||
826 | smi_info->handlers->start_transaction( | 868 | smi_info->handlers->start_transaction( |
827 | smi_info->si_sm, msg, 2); | 869 | smi_info->si_sm, msg, 2); |
828 | smi_info->si_state = SI_GETTING_FLAGS; | 870 | smi_info->si_state = SI_GETTING_FLAGS; |
829 | goto restart; | 871 | goto restart; |
872 | } | ||
830 | } | 873 | } |
831 | 874 | ||
832 | /* If we are currently idle, try to start the next message. */ | 875 | /* If we are currently idle, try to start the next message. */ |
@@ -846,19 +889,21 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, | |||
846 | */ | 889 | */ |
847 | atomic_set(&smi_info->req_events, 0); | 890 | atomic_set(&smi_info->req_events, 0); |
848 | 891 | ||
849 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 892 | /* |
850 | if (!smi_info->curr_msg) | 893 | * Take this opportunity to check the interrupt and |
851 | goto out; | 894 | * message enable state for the BMC. The BMC can be |
852 | 895 | * asynchronously reset, and may thus get interrupts | |
853 | smi_info->curr_msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); | 896 | * disable and messages disabled. |
854 | smi_info->curr_msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD; | 897 | */ |
855 | smi_info->curr_msg->data_size = 2; | 898 | if (smi_info->supports_event_msg_buff || smi_info->irq) { |
899 | start_check_enables(smi_info); | ||
900 | } else { | ||
901 | smi_info->curr_msg = alloc_msg_handle_irq(smi_info); | ||
902 | if (!smi_info->curr_msg) | ||
903 | goto out; | ||
856 | 904 | ||
857 | smi_info->handlers->start_transaction( | 905 | start_getting_events(smi_info); |
858 | smi_info->si_sm, | 906 | } |
859 | smi_info->curr_msg->data, | ||
860 | smi_info->curr_msg->data_size); | ||
861 | smi_info->si_state = SI_GETTING_EVENTS; | ||
862 | goto restart; | 907 | goto restart; |
863 | } | 908 | } |
864 | out: | 909 | out: |
@@ -879,8 +924,7 @@ static void check_start_timer_thread(struct smi_info *smi_info) | |||
879 | } | 924 | } |
880 | 925 | ||
881 | static void sender(void *send_info, | 926 | static void sender(void *send_info, |
882 | struct ipmi_smi_msg *msg, | 927 | struct ipmi_smi_msg *msg) |
883 | int priority) | ||
884 | { | 928 | { |
885 | struct smi_info *smi_info = send_info; | 929 | struct smi_info *smi_info = send_info; |
886 | enum si_sm_result result; | 930 | enum si_sm_result result; |
@@ -889,14 +933,8 @@ static void sender(void *send_info, | |||
889 | struct timeval t; | 933 | struct timeval t; |
890 | #endif | 934 | #endif |
891 | 935 | ||
892 | if (atomic_read(&smi_info->stop_operation)) { | 936 | BUG_ON(smi_info->waiting_msg); |
893 | msg->rsp[0] = msg->data[0] | 4; | 937 | smi_info->waiting_msg = msg; |
894 | msg->rsp[1] = msg->data[1]; | ||
895 | msg->rsp[2] = IPMI_ERR_UNSPECIFIED; | ||
896 | msg->rsp_size = 3; | ||
897 | deliver_recv_msg(smi_info, msg); | ||
898 | return; | ||
899 | } | ||
900 | 938 | ||
901 | #ifdef DEBUG_TIMING | 939 | #ifdef DEBUG_TIMING |
902 | do_gettimeofday(&t); | 940 | do_gettimeofday(&t); |
@@ -905,16 +943,16 @@ static void sender(void *send_info, | |||
905 | 943 | ||
906 | if (smi_info->run_to_completion) { | 944 | if (smi_info->run_to_completion) { |
907 | /* | 945 | /* |
908 | * If we are running to completion, then throw it in | 946 | * If we are running to completion, start it and run |
909 | * the list and run transactions until everything is | 947 | * transactions until everything is clear. |
910 | * clear. Priority doesn't matter here. | ||
911 | */ | 948 | */ |
949 | smi_info->curr_msg = smi_info->waiting_msg; | ||
950 | smi_info->waiting_msg = NULL; | ||
912 | 951 | ||
913 | /* | 952 | /* |
914 | * Run to completion means we are single-threaded, no | 953 | * Run to completion means we are single-threaded, no |
915 | * need for locks. | 954 | * need for locks. |
916 | */ | 955 | */ |
917 | list_add_tail(&(msg->link), &(smi_info->xmit_msgs)); | ||
918 | 956 | ||
919 | result = smi_event_handler(smi_info, 0); | 957 | result = smi_event_handler(smi_info, 0); |
920 | while (result != SI_SM_IDLE) { | 958 | while (result != SI_SM_IDLE) { |
@@ -926,11 +964,6 @@ static void sender(void *send_info, | |||
926 | } | 964 | } |
927 | 965 | ||
928 | spin_lock_irqsave(&smi_info->si_lock, flags); | 966 | spin_lock_irqsave(&smi_info->si_lock, flags); |
929 | if (priority > 0) | ||
930 | list_add_tail(&msg->link, &smi_info->hp_xmit_msgs); | ||
931 | else | ||
932 | list_add_tail(&msg->link, &smi_info->xmit_msgs); | ||
933 | |||
934 | check_start_timer_thread(smi_info); | 967 | check_start_timer_thread(smi_info); |
935 | spin_unlock_irqrestore(&smi_info->si_lock, flags); | 968 | spin_unlock_irqrestore(&smi_info->si_lock, flags); |
936 | } | 969 | } |
@@ -1068,8 +1101,7 @@ static void request_events(void *send_info) | |||
1068 | { | 1101 | { |
1069 | struct smi_info *smi_info = send_info; | 1102 | struct smi_info *smi_info = send_info; |
1070 | 1103 | ||
1071 | if (atomic_read(&smi_info->stop_operation) || | 1104 | if (!smi_info->has_event_buffer) |
1072 | !smi_info->has_event_buffer) | ||
1073 | return; | 1105 | return; |
1074 | 1106 | ||
1075 | atomic_set(&smi_info->req_events, 1); | 1107 | atomic_set(&smi_info->req_events, 1); |
@@ -1697,7 +1729,7 @@ static int parse_str(struct hotmod_vals *v, int *val, char *name, char **curr) | |||
1697 | } | 1729 | } |
1698 | *s = '\0'; | 1730 | *s = '\0'; |
1699 | s++; | 1731 | s++; |
1700 | for (i = 0; hotmod_ops[i].name; i++) { | 1732 | for (i = 0; v[i].name; i++) { |
1701 | if (strcmp(*curr, v[i].name) == 0) { | 1733 | if (strcmp(*curr, v[i].name) == 0) { |
1702 | *val = v[i].val; | 1734 | *val = v[i].val; |
1703 | *curr = s; | 1735 | *curr = s; |
@@ -2133,6 +2165,9 @@ static int try_init_spmi(struct SPMITable *spmi) | |||
2133 | case 3: /* BT */ | 2165 | case 3: /* BT */ |
2134 | info->si_type = SI_BT; | 2166 | info->si_type = SI_BT; |
2135 | break; | 2167 | break; |
2168 | case 4: /* SSIF, just ignore */ | ||
2169 | kfree(info); | ||
2170 | return -EIO; | ||
2136 | default: | 2171 | default: |
2137 | printk(KERN_INFO PFX "Unknown ACPI/SPMI SI type %d\n", | 2172 | printk(KERN_INFO PFX "Unknown ACPI/SPMI SI type %d\n", |
2138 | spmi->InterfaceType); | 2173 | spmi->InterfaceType); |
@@ -2250,6 +2285,8 @@ static int ipmi_pnp_probe(struct pnp_dev *dev, | |||
2250 | case 3: | 2285 | case 3: |
2251 | info->si_type = SI_BT; | 2286 | info->si_type = SI_BT; |
2252 | break; | 2287 | break; |
2288 | case 4: /* SSIF, just ignore */ | ||
2289 | goto err_free; | ||
2253 | default: | 2290 | default: |
2254 | dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp); | 2291 | dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp); |
2255 | goto err_free; | 2292 | goto err_free; |
@@ -2913,9 +2950,11 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2913 | goto out; | 2950 | goto out; |
2914 | } | 2951 | } |
2915 | 2952 | ||
2916 | if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) | 2953 | if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) { |
2917 | /* buffer is already enabled, nothing to do. */ | 2954 | /* buffer is already enabled, nothing to do. */ |
2955 | smi_info->supports_event_msg_buff = true; | ||
2918 | goto out; | 2956 | goto out; |
2957 | } | ||
2919 | 2958 | ||
2920 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | 2959 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; |
2921 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; | 2960 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; |
@@ -2948,6 +2987,9 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2948 | * that the event buffer is not supported. | 2987 | * that the event buffer is not supported. |
2949 | */ | 2988 | */ |
2950 | rv = -ENOENT; | 2989 | rv = -ENOENT; |
2990 | else | ||
2991 | smi_info->supports_event_msg_buff = true; | ||
2992 | |||
2951 | out: | 2993 | out: |
2952 | kfree(resp); | 2994 | kfree(resp); |
2953 | return rv; | 2995 | return rv; |
@@ -3188,15 +3230,10 @@ static void setup_xaction_handlers(struct smi_info *smi_info) | |||
3188 | 3230 | ||
3189 | static inline void wait_for_timer_and_thread(struct smi_info *smi_info) | 3231 | static inline void wait_for_timer_and_thread(struct smi_info *smi_info) |
3190 | { | 3232 | { |
3191 | if (smi_info->intf) { | 3233 | if (smi_info->thread != NULL) |
3192 | /* | 3234 | kthread_stop(smi_info->thread); |
3193 | * The timer and thread are only running if the | 3235 | if (smi_info->timer_running) |
3194 | * interface has been started up and registered. | ||
3195 | */ | ||
3196 | if (smi_info->thread != NULL) | ||
3197 | kthread_stop(smi_info->thread); | ||
3198 | del_timer_sync(&smi_info->si_timer); | 3236 | del_timer_sync(&smi_info->si_timer); |
3199 | } | ||
3200 | } | 3237 | } |
3201 | 3238 | ||
3202 | static struct ipmi_default_vals | 3239 | static struct ipmi_default_vals |
@@ -3274,8 +3311,8 @@ static int add_smi(struct smi_info *new_smi) | |||
3274 | int rv = 0; | 3311 | int rv = 0; |
3275 | 3312 | ||
3276 | printk(KERN_INFO PFX "Adding %s-specified %s state machine", | 3313 | printk(KERN_INFO PFX "Adding %s-specified %s state machine", |
3277 | ipmi_addr_src_to_str[new_smi->addr_source], | 3314 | ipmi_addr_src_to_str(new_smi->addr_source), |
3278 | si_to_str[new_smi->si_type]); | 3315 | si_to_str[new_smi->si_type]); |
3279 | mutex_lock(&smi_infos_lock); | 3316 | mutex_lock(&smi_infos_lock); |
3280 | if (!is_new_interface(new_smi)) { | 3317 | if (!is_new_interface(new_smi)) { |
3281 | printk(KERN_CONT " duplicate interface\n"); | 3318 | printk(KERN_CONT " duplicate interface\n"); |
@@ -3305,7 +3342,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3305 | printk(KERN_INFO PFX "Trying %s-specified %s state" | 3342 | printk(KERN_INFO PFX "Trying %s-specified %s state" |
3306 | " machine at %s address 0x%lx, slave address 0x%x," | 3343 | " machine at %s address 0x%lx, slave address 0x%x," |
3307 | " irq %d\n", | 3344 | " irq %d\n", |
3308 | ipmi_addr_src_to_str[new_smi->addr_source], | 3345 | ipmi_addr_src_to_str(new_smi->addr_source), |
3309 | si_to_str[new_smi->si_type], | 3346 | si_to_str[new_smi->si_type], |
3310 | addr_space_to_str[new_smi->io.addr_type], | 3347 | addr_space_to_str[new_smi->io.addr_type], |
3311 | new_smi->io.addr_data, | 3348 | new_smi->io.addr_data, |
@@ -3371,8 +3408,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3371 | setup_oem_data_handler(new_smi); | 3408 | setup_oem_data_handler(new_smi); |
3372 | setup_xaction_handlers(new_smi); | 3409 | setup_xaction_handlers(new_smi); |
3373 | 3410 | ||
3374 | INIT_LIST_HEAD(&(new_smi->xmit_msgs)); | 3411 | new_smi->waiting_msg = NULL; |
3375 | INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs)); | ||
3376 | new_smi->curr_msg = NULL; | 3412 | new_smi->curr_msg = NULL; |
3377 | atomic_set(&new_smi->req_events, 0); | 3413 | atomic_set(&new_smi->req_events, 0); |
3378 | new_smi->run_to_completion = false; | 3414 | new_smi->run_to_completion = false; |
@@ -3380,7 +3416,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3380 | atomic_set(&new_smi->stats[i], 0); | 3416 | atomic_set(&new_smi->stats[i], 0); |
3381 | 3417 | ||
3382 | new_smi->interrupt_disabled = true; | 3418 | new_smi->interrupt_disabled = true; |
3383 | atomic_set(&new_smi->stop_operation, 0); | ||
3384 | atomic_set(&new_smi->need_watch, 0); | 3419 | atomic_set(&new_smi->need_watch, 0); |
3385 | new_smi->intf_num = smi_num; | 3420 | new_smi->intf_num = smi_num; |
3386 | smi_num++; | 3421 | smi_num++; |
@@ -3394,9 +3429,15 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3394 | * timer to avoid racing with the timer. | 3429 | * timer to avoid racing with the timer. |
3395 | */ | 3430 | */ |
3396 | start_clear_flags(new_smi); | 3431 | start_clear_flags(new_smi); |
3397 | /* IRQ is defined to be set when non-zero. */ | 3432 | |
3398 | if (new_smi->irq) | 3433 | /* |
3399 | new_smi->si_state = SI_CLEARING_FLAGS_THEN_SET_IRQ; | 3434 | * IRQ is defined to be set when non-zero. req_events will |
3435 | * cause a global flags check that will enable interrupts. | ||
3436 | */ | ||
3437 | if (new_smi->irq) { | ||
3438 | new_smi->interrupt_disabled = false; | ||
3439 | atomic_set(&new_smi->req_events, 1); | ||
3440 | } | ||
3400 | 3441 | ||
3401 | if (!new_smi->dev) { | 3442 | if (!new_smi->dev) { |
3402 | /* | 3443 | /* |
@@ -3428,7 +3469,6 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3428 | new_smi, | 3469 | new_smi, |
3429 | &new_smi->device_id, | 3470 | &new_smi->device_id, |
3430 | new_smi->dev, | 3471 | new_smi->dev, |
3431 | "bmc", | ||
3432 | new_smi->slave_addr); | 3472 | new_smi->slave_addr); |
3433 | if (rv) { | 3473 | if (rv) { |
3434 | dev_err(new_smi->dev, "Unable to register device: error %d\n", | 3474 | dev_err(new_smi->dev, "Unable to register device: error %d\n", |
@@ -3466,15 +3506,15 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3466 | return 0; | 3506 | return 0; |
3467 | 3507 | ||
3468 | out_err_stop_timer: | 3508 | out_err_stop_timer: |
3469 | atomic_inc(&new_smi->stop_operation); | ||
3470 | wait_for_timer_and_thread(new_smi); | 3509 | wait_for_timer_and_thread(new_smi); |
3471 | 3510 | ||
3472 | out_err: | 3511 | out_err: |
3473 | new_smi->interrupt_disabled = true; | 3512 | new_smi->interrupt_disabled = true; |
3474 | 3513 | ||
3475 | if (new_smi->intf) { | 3514 | if (new_smi->intf) { |
3476 | ipmi_unregister_smi(new_smi->intf); | 3515 | ipmi_smi_t intf = new_smi->intf; |
3477 | new_smi->intf = NULL; | 3516 | new_smi->intf = NULL; |
3517 | ipmi_unregister_smi(intf); | ||
3478 | } | 3518 | } |
3479 | 3519 | ||
3480 | if (new_smi->irq_cleanup) { | 3520 | if (new_smi->irq_cleanup) { |
@@ -3653,60 +3693,49 @@ module_init(init_ipmi_si); | |||
3653 | static void cleanup_one_si(struct smi_info *to_clean) | 3693 | static void cleanup_one_si(struct smi_info *to_clean) |
3654 | { | 3694 | { |
3655 | int rv = 0; | 3695 | int rv = 0; |
3656 | unsigned long flags; | ||
3657 | 3696 | ||
3658 | if (!to_clean) | 3697 | if (!to_clean) |
3659 | return; | 3698 | return; |
3660 | 3699 | ||
3700 | if (to_clean->intf) { | ||
3701 | ipmi_smi_t intf = to_clean->intf; | ||
3702 | |||
3703 | to_clean->intf = NULL; | ||
3704 | rv = ipmi_unregister_smi(intf); | ||
3705 | if (rv) { | ||
3706 | pr_err(PFX "Unable to unregister device: errno=%d\n", | ||
3707 | rv); | ||
3708 | } | ||
3709 | } | ||
3710 | |||
3661 | if (to_clean->dev) | 3711 | if (to_clean->dev) |
3662 | dev_set_drvdata(to_clean->dev, NULL); | 3712 | dev_set_drvdata(to_clean->dev, NULL); |
3663 | 3713 | ||
3664 | list_del(&to_clean->link); | 3714 | list_del(&to_clean->link); |
3665 | 3715 | ||
3666 | /* Tell the driver that we are shutting down. */ | ||
3667 | atomic_inc(&to_clean->stop_operation); | ||
3668 | |||
3669 | /* | 3716 | /* |
3670 | * Make sure the timer and thread are stopped and will not run | 3717 | * Make sure that interrupts, the timer and the thread are |
3671 | * again. | 3718 | * stopped and will not run again. |
3672 | */ | 3719 | */ |
3720 | if (to_clean->irq_cleanup) | ||
3721 | to_clean->irq_cleanup(to_clean); | ||
3673 | wait_for_timer_and_thread(to_clean); | 3722 | wait_for_timer_and_thread(to_clean); |
3674 | 3723 | ||
3675 | /* | 3724 | /* |
3676 | * Timeouts are stopped, now make sure the interrupts are off | 3725 | * Timeouts are stopped, now make sure the interrupts are off |
3677 | * for the device. A little tricky with locks to make sure | 3726 | * in the BMC. Note that timers and CPU interrupts are off, |
3678 | * there are no races. | 3727 | * so no need for locks. |
3679 | */ | 3728 | */ |
3680 | spin_lock_irqsave(&to_clean->si_lock, flags); | ||
3681 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { | 3729 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { |
3682 | spin_unlock_irqrestore(&to_clean->si_lock, flags); | ||
3683 | poll(to_clean); | 3730 | poll(to_clean); |
3684 | schedule_timeout_uninterruptible(1); | 3731 | schedule_timeout_uninterruptible(1); |
3685 | spin_lock_irqsave(&to_clean->si_lock, flags); | ||
3686 | } | 3732 | } |
3687 | disable_si_irq(to_clean); | 3733 | disable_si_irq(to_clean); |
3688 | spin_unlock_irqrestore(&to_clean->si_lock, flags); | ||
3689 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { | 3734 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { |
3690 | poll(to_clean); | 3735 | poll(to_clean); |
3691 | schedule_timeout_uninterruptible(1); | 3736 | schedule_timeout_uninterruptible(1); |
3692 | } | 3737 | } |
3693 | 3738 | ||
3694 | /* Clean up interrupts and make sure that everything is done. */ | ||
3695 | if (to_clean->irq_cleanup) | ||
3696 | to_clean->irq_cleanup(to_clean); | ||
3697 | while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) { | ||
3698 | poll(to_clean); | ||
3699 | schedule_timeout_uninterruptible(1); | ||
3700 | } | ||
3701 | |||
3702 | if (to_clean->intf) | ||
3703 | rv = ipmi_unregister_smi(to_clean->intf); | ||
3704 | |||
3705 | if (rv) { | ||
3706 | printk(KERN_ERR PFX "Unable to unregister device: errno=%d\n", | ||
3707 | rv); | ||
3708 | } | ||
3709 | |||
3710 | if (to_clean->handlers) | 3739 | if (to_clean->handlers) |
3711 | to_clean->handlers->cleanup(to_clean->si_sm); | 3740 | to_clean->handlers->cleanup(to_clean->si_sm); |
3712 | 3741 | ||
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c new file mode 100644 index 000000000000..e178ac27e73c --- /dev/null +++ b/drivers/char/ipmi/ipmi_ssif.c | |||
@@ -0,0 +1,1870 @@ | |||
1 | /* | ||
2 | * ipmi_ssif.c | ||
3 | * | ||
4 | * The interface to the IPMI driver for SMBus access to a SMBus | ||
5 | * compliant device. Called SSIF by the IPMI spec. | ||
6 | * | ||
7 | * Author: Intel Corporation | ||
8 | * Todd Davis <todd.c.davis@intel.com> | ||
9 | * | ||
10 | * Rewritten by Corey Minyard <minyard@acm.org> to support the | ||
11 | * non-blocking I2C interface, add support for multi-part | ||
12 | * transactions, add PEC support, and general clenaup. | ||
13 | * | ||
14 | * Copyright 2003 Intel Corporation | ||
15 | * Copyright 2005 MontaVista Software | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify it | ||
18 | * under the terms of the GNU General Public License as published by the | ||
19 | * Free Software Foundation; either version 2 of the License, or (at your | ||
20 | * option) any later version. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * This file holds the "policy" for the interface to the SSIF state | ||
25 | * machine. It does the configuration, handles timers and interrupts, | ||
26 | * and drives the real SSIF state machine. | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * TODO: Figure out how to use SMB alerts. This will require a new | ||
31 | * interface into the I2C driver, I believe. | ||
32 | */ | ||
33 | |||
34 | #include <linux/version.h> | ||
35 | #if defined(MODVERSIONS) | ||
36 | #include <linux/modversions.h> | ||
37 | #endif | ||
38 | |||
39 | #include <linux/module.h> | ||
40 | #include <linux/moduleparam.h> | ||
41 | #include <linux/sched.h> | ||
42 | #include <linux/seq_file.h> | ||
43 | #include <linux/timer.h> | ||
44 | #include <linux/delay.h> | ||
45 | #include <linux/errno.h> | ||
46 | #include <linux/spinlock.h> | ||
47 | #include <linux/slab.h> | ||
48 | #include <linux/list.h> | ||
49 | #include <linux/i2c.h> | ||
50 | #include <linux/ipmi_smi.h> | ||
51 | #include <linux/init.h> | ||
52 | #include <linux/dmi.h> | ||
53 | #include <linux/kthread.h> | ||
54 | #include <linux/acpi.h> | ||
55 | |||
56 | #define PFX "ipmi_ssif: " | ||
57 | #define DEVICE_NAME "ipmi_ssif" | ||
58 | |||
59 | #define IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD 0x57 | ||
60 | |||
61 | #define SSIF_IPMI_REQUEST 2 | ||
62 | #define SSIF_IPMI_MULTI_PART_REQUEST_START 6 | ||
63 | #define SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE 7 | ||
64 | #define SSIF_IPMI_RESPONSE 3 | ||
65 | #define SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE 9 | ||
66 | |||
67 | /* ssif_debug is a bit-field | ||
68 | * SSIF_DEBUG_MSG - commands and their responses | ||
69 | * SSIF_DEBUG_STATES - message states | ||
70 | * SSIF_DEBUG_TIMING - Measure times between events in the driver | ||
71 | */ | ||
72 | #define SSIF_DEBUG_TIMING 4 | ||
73 | #define SSIF_DEBUG_STATE 2 | ||
74 | #define SSIF_DEBUG_MSG 1 | ||
75 | #define SSIF_NODEBUG 0 | ||
76 | #define SSIF_DEFAULT_DEBUG (SSIF_NODEBUG) | ||
77 | |||
78 | /* | ||
79 | * Timer values | ||
80 | */ | ||
81 | #define SSIF_MSG_USEC 20000 /* 20ms between message tries. */ | ||
82 | #define SSIF_MSG_PART_USEC 5000 /* 5ms for a message part */ | ||
83 | |||
84 | /* How many times to we retry sending/receiving the message. */ | ||
85 | #define SSIF_SEND_RETRIES 5 | ||
86 | #define SSIF_RECV_RETRIES 250 | ||
87 | |||
88 | #define SSIF_MSG_MSEC (SSIF_MSG_USEC / 1000) | ||
89 | #define SSIF_MSG_JIFFIES ((SSIF_MSG_USEC * 1000) / TICK_NSEC) | ||
90 | #define SSIF_MSG_PART_JIFFIES ((SSIF_MSG_PART_USEC * 1000) / TICK_NSEC) | ||
91 | |||
92 | enum ssif_intf_state { | ||
93 | SSIF_NORMAL, | ||
94 | SSIF_GETTING_FLAGS, | ||
95 | SSIF_GETTING_EVENTS, | ||
96 | SSIF_CLEARING_FLAGS, | ||
97 | SSIF_GETTING_MESSAGES, | ||
98 | /* FIXME - add watchdog stuff. */ | ||
99 | }; | ||
100 | |||
101 | #define SSIF_IDLE(ssif) ((ssif)->ssif_state == SSIF_NORMAL \ | ||
102 | && (ssif)->curr_msg == NULL) | ||
103 | |||
104 | /* | ||
105 | * Indexes into stats[] in ssif_info below. | ||
106 | */ | ||
107 | enum ssif_stat_indexes { | ||
108 | /* Number of total messages sent. */ | ||
109 | SSIF_STAT_sent_messages = 0, | ||
110 | |||
111 | /* | ||
112 | * Number of message parts sent. Messages may be broken into | ||
113 | * parts if they are long. | ||
114 | */ | ||
115 | SSIF_STAT_sent_messages_parts, | ||
116 | |||
117 | /* | ||
118 | * Number of time a message was retried. | ||
119 | */ | ||
120 | SSIF_STAT_send_retries, | ||
121 | |||
122 | /* | ||
123 | * Number of times the send of a message failed. | ||
124 | */ | ||
125 | SSIF_STAT_send_errors, | ||
126 | |||
127 | /* | ||
128 | * Number of message responses received. | ||
129 | */ | ||
130 | SSIF_STAT_received_messages, | ||
131 | |||
132 | /* | ||
133 | * Number of message fragments received. | ||
134 | */ | ||
135 | SSIF_STAT_received_message_parts, | ||
136 | |||
137 | /* | ||
138 | * Number of times the receive of a message was retried. | ||
139 | */ | ||
140 | SSIF_STAT_receive_retries, | ||
141 | |||
142 | /* | ||
143 | * Number of errors receiving messages. | ||
144 | */ | ||
145 | SSIF_STAT_receive_errors, | ||
146 | |||
147 | /* | ||
148 | * Number of times a flag fetch was requested. | ||
149 | */ | ||
150 | SSIF_STAT_flag_fetches, | ||
151 | |||
152 | /* | ||
153 | * Number of times the hardware didn't follow the state machine. | ||
154 | */ | ||
155 | SSIF_STAT_hosed, | ||
156 | |||
157 | /* | ||
158 | * Number of received events. | ||
159 | */ | ||
160 | SSIF_STAT_events, | ||
161 | |||
162 | /* Number of asyncronous messages received. */ | ||
163 | SSIF_STAT_incoming_messages, | ||
164 | |||
165 | /* Number of watchdog pretimeouts. */ | ||
166 | SSIF_STAT_watchdog_pretimeouts, | ||
167 | |||
168 | /* Always add statistics before this value, it must be last. */ | ||
169 | SSIF_NUM_STATS | ||
170 | }; | ||
171 | |||
172 | struct ssif_addr_info { | ||
173 | unsigned short addr; | ||
174 | struct i2c_board_info binfo; | ||
175 | char *adapter_name; | ||
176 | int debug; | ||
177 | int slave_addr; | ||
178 | enum ipmi_addr_src addr_src; | ||
179 | union ipmi_smi_info_union addr_info; | ||
180 | |||
181 | struct mutex clients_mutex; | ||
182 | struct list_head clients; | ||
183 | |||
184 | struct list_head link; | ||
185 | }; | ||
186 | |||
187 | struct ssif_info; | ||
188 | |||
189 | typedef void (*ssif_i2c_done)(struct ssif_info *ssif_info, int result, | ||
190 | unsigned char *data, unsigned int len); | ||
191 | |||
192 | struct ssif_info { | ||
193 | ipmi_smi_t intf; | ||
194 | int intf_num; | ||
195 | spinlock_t lock; | ||
196 | struct ipmi_smi_msg *waiting_msg; | ||
197 | struct ipmi_smi_msg *curr_msg; | ||
198 | enum ssif_intf_state ssif_state; | ||
199 | unsigned long ssif_debug; | ||
200 | |||
201 | struct ipmi_smi_handlers handlers; | ||
202 | |||
203 | enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */ | ||
204 | union ipmi_smi_info_union addr_info; | ||
205 | |||
206 | /* | ||
207 | * Flags from the last GET_MSG_FLAGS command, used when an ATTN | ||
208 | * is set to hold the flags until we are done handling everything | ||
209 | * from the flags. | ||
210 | */ | ||
211 | #define RECEIVE_MSG_AVAIL 0x01 | ||
212 | #define EVENT_MSG_BUFFER_FULL 0x02 | ||
213 | #define WDT_PRE_TIMEOUT_INT 0x08 | ||
214 | unsigned char msg_flags; | ||
215 | |||
216 | bool has_event_buffer; | ||
217 | |||
218 | /* | ||
219 | * If set to true, this will request events the next time the | ||
220 | * state machine is idle. | ||
221 | */ | ||
222 | bool req_events; | ||
223 | |||
224 | /* | ||
225 | * If set to true, this will request flags the next time the | ||
226 | * state machine is idle. | ||
227 | */ | ||
228 | bool req_flags; | ||
229 | |||
230 | /* | ||
231 | * Used to perform timer operations when run-to-completion | ||
232 | * mode is on. This is a countdown timer. | ||
233 | */ | ||
234 | int rtc_us_timer; | ||
235 | |||
236 | /* Used for sending/receiving data. +1 for the length. */ | ||
237 | unsigned char data[IPMI_MAX_MSG_LENGTH + 1]; | ||
238 | unsigned int data_len; | ||
239 | |||
240 | /* Temp receive buffer, gets copied into data. */ | ||
241 | unsigned char recv[I2C_SMBUS_BLOCK_MAX]; | ||
242 | |||
243 | struct i2c_client *client; | ||
244 | ssif_i2c_done done_handler; | ||
245 | |||
246 | /* Thread interface handling */ | ||
247 | struct task_struct *thread; | ||
248 | struct completion wake_thread; | ||
249 | bool stopping; | ||
250 | int i2c_read_write; | ||
251 | int i2c_command; | ||
252 | unsigned char *i2c_data; | ||
253 | unsigned int i2c_size; | ||
254 | |||
255 | /* From the device id response. */ | ||
256 | struct ipmi_device_id device_id; | ||
257 | |||
258 | struct timer_list retry_timer; | ||
259 | int retries_left; | ||
260 | |||
261 | /* Info from SSIF cmd */ | ||
262 | unsigned char max_xmit_msg_size; | ||
263 | unsigned char max_recv_msg_size; | ||
264 | unsigned int multi_support; | ||
265 | int supports_pec; | ||
266 | |||
267 | #define SSIF_NO_MULTI 0 | ||
268 | #define SSIF_MULTI_2_PART 1 | ||
269 | #define SSIF_MULTI_n_PART 2 | ||
270 | unsigned char *multi_data; | ||
271 | unsigned int multi_len; | ||
272 | unsigned int multi_pos; | ||
273 | |||
274 | atomic_t stats[SSIF_NUM_STATS]; | ||
275 | }; | ||
276 | |||
277 | #define ssif_inc_stat(ssif, stat) \ | ||
278 | atomic_inc(&(ssif)->stats[SSIF_STAT_ ## stat]) | ||
279 | #define ssif_get_stat(ssif, stat) \ | ||
280 | ((unsigned int) atomic_read(&(ssif)->stats[SSIF_STAT_ ## stat])) | ||
281 | |||
282 | static bool initialized; | ||
283 | |||
284 | static atomic_t next_intf = ATOMIC_INIT(0); | ||
285 | |||
286 | static void return_hosed_msg(struct ssif_info *ssif_info, | ||
287 | struct ipmi_smi_msg *msg); | ||
288 | static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags); | ||
289 | static int start_send(struct ssif_info *ssif_info, | ||
290 | unsigned char *data, | ||
291 | unsigned int len); | ||
292 | |||
293 | static unsigned long *ipmi_ssif_lock_cond(struct ssif_info *ssif_info, | ||
294 | unsigned long *flags) | ||
295 | { | ||
296 | spin_lock_irqsave(&ssif_info->lock, *flags); | ||
297 | return flags; | ||
298 | } | ||
299 | |||
300 | static void ipmi_ssif_unlock_cond(struct ssif_info *ssif_info, | ||
301 | unsigned long *flags) | ||
302 | { | ||
303 | spin_unlock_irqrestore(&ssif_info->lock, *flags); | ||
304 | } | ||
305 | |||
306 | static void deliver_recv_msg(struct ssif_info *ssif_info, | ||
307 | struct ipmi_smi_msg *msg) | ||
308 | { | ||
309 | ipmi_smi_t intf = ssif_info->intf; | ||
310 | |||
311 | if (!intf) { | ||
312 | ipmi_free_smi_msg(msg); | ||
313 | } else if (msg->rsp_size < 0) { | ||
314 | return_hosed_msg(ssif_info, msg); | ||
315 | pr_err(PFX | ||
316 | "Malformed message in deliver_recv_msg: rsp_size = %d\n", | ||
317 | msg->rsp_size); | ||
318 | } else { | ||
319 | ipmi_smi_msg_received(intf, msg); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | static void return_hosed_msg(struct ssif_info *ssif_info, | ||
324 | struct ipmi_smi_msg *msg) | ||
325 | { | ||
326 | ssif_inc_stat(ssif_info, hosed); | ||
327 | |||
328 | /* Make it a response */ | ||
329 | msg->rsp[0] = msg->data[0] | 4; | ||
330 | msg->rsp[1] = msg->data[1]; | ||
331 | msg->rsp[2] = 0xFF; /* Unknown error. */ | ||
332 | msg->rsp_size = 3; | ||
333 | |||
334 | deliver_recv_msg(ssif_info, msg); | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Must be called with the message lock held. This will release the | ||
339 | * message lock. Note that the caller will check SSIF_IDLE and start a | ||
340 | * new operation, so there is no need to check for new messages to | ||
341 | * start in here. | ||
342 | */ | ||
343 | static void start_clear_flags(struct ssif_info *ssif_info, unsigned long *flags) | ||
344 | { | ||
345 | unsigned char msg[3]; | ||
346 | |||
347 | ssif_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; | ||
348 | ssif_info->ssif_state = SSIF_CLEARING_FLAGS; | ||
349 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
350 | |||
351 | /* Make sure the watchdog pre-timeout flag is not set at startup. */ | ||
352 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
353 | msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD; | ||
354 | msg[2] = WDT_PRE_TIMEOUT_INT; | ||
355 | |||
356 | if (start_send(ssif_info, msg, 3) != 0) { | ||
357 | /* Error, just go to normal state. */ | ||
358 | ssif_info->ssif_state = SSIF_NORMAL; | ||
359 | } | ||
360 | } | ||
361 | |||
362 | static void start_flag_fetch(struct ssif_info *ssif_info, unsigned long *flags) | ||
363 | { | ||
364 | unsigned char mb[2]; | ||
365 | |||
366 | ssif_info->req_flags = false; | ||
367 | ssif_info->ssif_state = SSIF_GETTING_FLAGS; | ||
368 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
369 | |||
370 | mb[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
371 | mb[1] = IPMI_GET_MSG_FLAGS_CMD; | ||
372 | if (start_send(ssif_info, mb, 2) != 0) | ||
373 | ssif_info->ssif_state = SSIF_NORMAL; | ||
374 | } | ||
375 | |||
376 | static void check_start_send(struct ssif_info *ssif_info, unsigned long *flags, | ||
377 | struct ipmi_smi_msg *msg) | ||
378 | { | ||
379 | if (start_send(ssif_info, msg->data, msg->data_size) != 0) { | ||
380 | unsigned long oflags; | ||
381 | |||
382 | flags = ipmi_ssif_lock_cond(ssif_info, &oflags); | ||
383 | ssif_info->curr_msg = NULL; | ||
384 | ssif_info->ssif_state = SSIF_NORMAL; | ||
385 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
386 | ipmi_free_smi_msg(msg); | ||
387 | } | ||
388 | } | ||
389 | |||
390 | static void start_event_fetch(struct ssif_info *ssif_info, unsigned long *flags) | ||
391 | { | ||
392 | struct ipmi_smi_msg *msg; | ||
393 | |||
394 | ssif_info->req_events = false; | ||
395 | |||
396 | msg = ipmi_alloc_smi_msg(); | ||
397 | if (!msg) { | ||
398 | ssif_info->ssif_state = SSIF_NORMAL; | ||
399 | return; | ||
400 | } | ||
401 | |||
402 | ssif_info->curr_msg = msg; | ||
403 | ssif_info->ssif_state = SSIF_GETTING_EVENTS; | ||
404 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
405 | |||
406 | msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
407 | msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD; | ||
408 | msg->data_size = 2; | ||
409 | |||
410 | check_start_send(ssif_info, flags, msg); | ||
411 | } | ||
412 | |||
413 | static void start_recv_msg_fetch(struct ssif_info *ssif_info, | ||
414 | unsigned long *flags) | ||
415 | { | ||
416 | struct ipmi_smi_msg *msg; | ||
417 | |||
418 | msg = ipmi_alloc_smi_msg(); | ||
419 | if (!msg) { | ||
420 | ssif_info->ssif_state = SSIF_NORMAL; | ||
421 | return; | ||
422 | } | ||
423 | |||
424 | ssif_info->curr_msg = msg; | ||
425 | ssif_info->ssif_state = SSIF_GETTING_MESSAGES; | ||
426 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
427 | |||
428 | msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2); | ||
429 | msg->data[1] = IPMI_GET_MSG_CMD; | ||
430 | msg->data_size = 2; | ||
431 | |||
432 | check_start_send(ssif_info, flags, msg); | ||
433 | } | ||
434 | |||
435 | /* | ||
436 | * Must be called with the message lock held. This will release the | ||
437 | * message lock. Note that the caller will check SSIF_IDLE and start a | ||
438 | * new operation, so there is no need to check for new messages to | ||
439 | * start in here. | ||
440 | */ | ||
441 | static void handle_flags(struct ssif_info *ssif_info, unsigned long *flags) | ||
442 | { | ||
443 | if (ssif_info->msg_flags & WDT_PRE_TIMEOUT_INT) { | ||
444 | ipmi_smi_t intf = ssif_info->intf; | ||
445 | /* Watchdog pre-timeout */ | ||
446 | ssif_inc_stat(ssif_info, watchdog_pretimeouts); | ||
447 | start_clear_flags(ssif_info, flags); | ||
448 | if (intf) | ||
449 | ipmi_smi_watchdog_pretimeout(intf); | ||
450 | } else if (ssif_info->msg_flags & RECEIVE_MSG_AVAIL) | ||
451 | /* Messages available. */ | ||
452 | start_recv_msg_fetch(ssif_info, flags); | ||
453 | else if (ssif_info->msg_flags & EVENT_MSG_BUFFER_FULL) | ||
454 | /* Events available. */ | ||
455 | start_event_fetch(ssif_info, flags); | ||
456 | else { | ||
457 | ssif_info->ssif_state = SSIF_NORMAL; | ||
458 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
459 | } | ||
460 | } | ||
461 | |||
462 | static int ipmi_ssif_thread(void *data) | ||
463 | { | ||
464 | struct ssif_info *ssif_info = data; | ||
465 | |||
466 | while (!kthread_should_stop()) { | ||
467 | int result; | ||
468 | |||
469 | /* Wait for something to do */ | ||
470 | wait_for_completion(&ssif_info->wake_thread); | ||
471 | init_completion(&ssif_info->wake_thread); | ||
472 | |||
473 | if (ssif_info->stopping) | ||
474 | break; | ||
475 | |||
476 | if (ssif_info->i2c_read_write == I2C_SMBUS_WRITE) { | ||
477 | result = i2c_smbus_write_block_data( | ||
478 | ssif_info->client, SSIF_IPMI_REQUEST, | ||
479 | ssif_info->i2c_data[0], | ||
480 | ssif_info->i2c_data + 1); | ||
481 | ssif_info->done_handler(ssif_info, result, NULL, 0); | ||
482 | } else { | ||
483 | result = i2c_smbus_read_block_data( | ||
484 | ssif_info->client, SSIF_IPMI_RESPONSE, | ||
485 | ssif_info->i2c_data); | ||
486 | if (result < 0) | ||
487 | ssif_info->done_handler(ssif_info, result, | ||
488 | NULL, 0); | ||
489 | else | ||
490 | ssif_info->done_handler(ssif_info, 0, | ||
491 | ssif_info->i2c_data, | ||
492 | result); | ||
493 | } | ||
494 | } | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static int ssif_i2c_send(struct ssif_info *ssif_info, | ||
500 | ssif_i2c_done handler, | ||
501 | int read_write, int command, | ||
502 | unsigned char *data, unsigned int size) | ||
503 | { | ||
504 | ssif_info->done_handler = handler; | ||
505 | |||
506 | ssif_info->i2c_read_write = read_write; | ||
507 | ssif_info->i2c_command = command; | ||
508 | ssif_info->i2c_data = data; | ||
509 | ssif_info->i2c_size = size; | ||
510 | complete(&ssif_info->wake_thread); | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | |||
515 | static void msg_done_handler(struct ssif_info *ssif_info, int result, | ||
516 | unsigned char *data, unsigned int len); | ||
517 | |||
518 | static void retry_timeout(unsigned long data) | ||
519 | { | ||
520 | struct ssif_info *ssif_info = (void *) data; | ||
521 | int rv; | ||
522 | |||
523 | if (ssif_info->stopping) | ||
524 | return; | ||
525 | |||
526 | ssif_info->rtc_us_timer = 0; | ||
527 | |||
528 | rv = ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ, | ||
529 | SSIF_IPMI_RESPONSE, | ||
530 | ssif_info->recv, I2C_SMBUS_BLOCK_DATA); | ||
531 | if (rv < 0) { | ||
532 | /* request failed, just return the error. */ | ||
533 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
534 | pr_info("Error from i2c_non_blocking_op(5)\n"); | ||
535 | |||
536 | msg_done_handler(ssif_info, -EIO, NULL, 0); | ||
537 | } | ||
538 | } | ||
539 | |||
540 | static int start_resend(struct ssif_info *ssif_info); | ||
541 | |||
542 | static void msg_done_handler(struct ssif_info *ssif_info, int result, | ||
543 | unsigned char *data, unsigned int len) | ||
544 | { | ||
545 | struct ipmi_smi_msg *msg; | ||
546 | unsigned long oflags, *flags; | ||
547 | int rv; | ||
548 | |||
549 | /* | ||
550 | * We are single-threaded here, so no need for a lock until we | ||
551 | * start messing with driver states or the queues. | ||
552 | */ | ||
553 | |||
554 | if (result < 0) { | ||
555 | ssif_info->retries_left--; | ||
556 | if (ssif_info->retries_left > 0) { | ||
557 | ssif_inc_stat(ssif_info, receive_retries); | ||
558 | |||
559 | mod_timer(&ssif_info->retry_timer, | ||
560 | jiffies + SSIF_MSG_JIFFIES); | ||
561 | ssif_info->rtc_us_timer = SSIF_MSG_USEC; | ||
562 | return; | ||
563 | } | ||
564 | |||
565 | ssif_inc_stat(ssif_info, receive_errors); | ||
566 | |||
567 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
568 | pr_info("Error in msg_done_handler: %d\n", result); | ||
569 | len = 0; | ||
570 | goto continue_op; | ||
571 | } | ||
572 | |||
573 | if ((len > 1) && (ssif_info->multi_pos == 0) | ||
574 | && (data[0] == 0x00) && (data[1] == 0x01)) { | ||
575 | /* Start of multi-part read. Start the next transaction. */ | ||
576 | int i; | ||
577 | |||
578 | ssif_inc_stat(ssif_info, received_message_parts); | ||
579 | |||
580 | /* Remove the multi-part read marker. */ | ||
581 | for (i = 0; i < (len-2); i++) | ||
582 | ssif_info->data[i] = data[i+2]; | ||
583 | len -= 2; | ||
584 | ssif_info->multi_len = len; | ||
585 | ssif_info->multi_pos = 1; | ||
586 | |||
587 | rv = ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ, | ||
588 | SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE, | ||
589 | ssif_info->recv, I2C_SMBUS_BLOCK_DATA); | ||
590 | if (rv < 0) { | ||
591 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
592 | pr_info("Error from i2c_non_blocking_op(1)\n"); | ||
593 | |||
594 | result = -EIO; | ||
595 | } else | ||
596 | return; | ||
597 | } else if (ssif_info->multi_pos) { | ||
598 | /* Middle of multi-part read. Start the next transaction. */ | ||
599 | int i; | ||
600 | unsigned char blocknum; | ||
601 | |||
602 | if (len == 0) { | ||
603 | result = -EIO; | ||
604 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
605 | pr_info(PFX "Middle message with no data\n"); | ||
606 | |||
607 | goto continue_op; | ||
608 | } | ||
609 | |||
610 | blocknum = data[ssif_info->multi_len]; | ||
611 | |||
612 | if (ssif_info->multi_len+len-1 > IPMI_MAX_MSG_LENGTH) { | ||
613 | /* Received message too big, abort the operation. */ | ||
614 | result = -E2BIG; | ||
615 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
616 | pr_info("Received message too big\n"); | ||
617 | |||
618 | goto continue_op; | ||
619 | } | ||
620 | |||
621 | /* Remove the blocknum from the data. */ | ||
622 | for (i = 0; i < (len-1); i++) | ||
623 | ssif_info->data[i+ssif_info->multi_len] = data[i+1]; | ||
624 | len--; | ||
625 | ssif_info->multi_len += len; | ||
626 | if (blocknum == 0xff) { | ||
627 | /* End of read */ | ||
628 | len = ssif_info->multi_len; | ||
629 | data = ssif_info->data; | ||
630 | } else if ((blocknum+1) != ssif_info->multi_pos) { | ||
631 | /* | ||
632 | * Out of sequence block, just abort. Block | ||
633 | * numbers start at zero for the second block, | ||
634 | * but multi_pos starts at one, so the +1. | ||
635 | */ | ||
636 | result = -EIO; | ||
637 | } else { | ||
638 | ssif_inc_stat(ssif_info, received_message_parts); | ||
639 | |||
640 | ssif_info->multi_pos++; | ||
641 | |||
642 | rv = ssif_i2c_send(ssif_info, msg_done_handler, | ||
643 | I2C_SMBUS_READ, | ||
644 | SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE, | ||
645 | ssif_info->recv, | ||
646 | I2C_SMBUS_BLOCK_DATA); | ||
647 | if (rv < 0) { | ||
648 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
649 | pr_info(PFX | ||
650 | "Error from i2c_non_blocking_op(2)\n"); | ||
651 | |||
652 | result = -EIO; | ||
653 | } else | ||
654 | return; | ||
655 | } | ||
656 | } | ||
657 | |||
658 | if (result < 0) { | ||
659 | ssif_inc_stat(ssif_info, receive_errors); | ||
660 | } else { | ||
661 | ssif_inc_stat(ssif_info, received_messages); | ||
662 | ssif_inc_stat(ssif_info, received_message_parts); | ||
663 | } | ||
664 | |||
665 | |||
666 | continue_op: | ||
667 | if (ssif_info->ssif_debug & SSIF_DEBUG_STATE) | ||
668 | pr_info(PFX "DONE 1: state = %d, result=%d.\n", | ||
669 | ssif_info->ssif_state, result); | ||
670 | |||
671 | flags = ipmi_ssif_lock_cond(ssif_info, &oflags); | ||
672 | msg = ssif_info->curr_msg; | ||
673 | if (msg) { | ||
674 | msg->rsp_size = len; | ||
675 | if (msg->rsp_size > IPMI_MAX_MSG_LENGTH) | ||
676 | msg->rsp_size = IPMI_MAX_MSG_LENGTH; | ||
677 | memcpy(msg->rsp, data, msg->rsp_size); | ||
678 | ssif_info->curr_msg = NULL; | ||
679 | } | ||
680 | |||
681 | switch (ssif_info->ssif_state) { | ||
682 | case SSIF_NORMAL: | ||
683 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
684 | if (!msg) | ||
685 | break; | ||
686 | |||
687 | if (result < 0) | ||
688 | return_hosed_msg(ssif_info, msg); | ||
689 | else | ||
690 | deliver_recv_msg(ssif_info, msg); | ||
691 | break; | ||
692 | |||
693 | case SSIF_GETTING_FLAGS: | ||
694 | /* We got the flags from the SSIF, now handle them. */ | ||
695 | if ((result < 0) || (len < 4) || (data[2] != 0)) { | ||
696 | /* | ||
697 | * Error fetching flags, or invalid length, | ||
698 | * just give up for now. | ||
699 | */ | ||
700 | ssif_info->ssif_state = SSIF_NORMAL; | ||
701 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
702 | pr_warn(PFX "Error getting flags: %d %d, %x\n", | ||
703 | result, len, data[2]); | ||
704 | } else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 | ||
705 | || data[1] != IPMI_GET_MSG_FLAGS_CMD) { | ||
706 | pr_warn(PFX "Invalid response getting flags: %x %x\n", | ||
707 | data[0], data[1]); | ||
708 | } else { | ||
709 | ssif_inc_stat(ssif_info, flag_fetches); | ||
710 | ssif_info->msg_flags = data[3]; | ||
711 | handle_flags(ssif_info, flags); | ||
712 | } | ||
713 | break; | ||
714 | |||
715 | case SSIF_CLEARING_FLAGS: | ||
716 | /* We cleared the flags. */ | ||
717 | if ((result < 0) || (len < 3) || (data[2] != 0)) { | ||
718 | /* Error clearing flags */ | ||
719 | pr_warn(PFX "Error clearing flags: %d %d, %x\n", | ||
720 | result, len, data[2]); | ||
721 | } else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 | ||
722 | || data[1] != IPMI_CLEAR_MSG_FLAGS_CMD) { | ||
723 | pr_warn(PFX "Invalid response clearing flags: %x %x\n", | ||
724 | data[0], data[1]); | ||
725 | } | ||
726 | ssif_info->ssif_state = SSIF_NORMAL; | ||
727 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
728 | break; | ||
729 | |||
730 | case SSIF_GETTING_EVENTS: | ||
731 | if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) { | ||
732 | /* Error getting event, probably done. */ | ||
733 | msg->done(msg); | ||
734 | |||
735 | /* Take off the event flag. */ | ||
736 | ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; | ||
737 | handle_flags(ssif_info, flags); | ||
738 | } else if (msg->rsp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 | ||
739 | || msg->rsp[1] != IPMI_READ_EVENT_MSG_BUFFER_CMD) { | ||
740 | pr_warn(PFX "Invalid response getting events: %x %x\n", | ||
741 | msg->rsp[0], msg->rsp[1]); | ||
742 | msg->done(msg); | ||
743 | /* Take off the event flag. */ | ||
744 | ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL; | ||
745 | handle_flags(ssif_info, flags); | ||
746 | } else { | ||
747 | handle_flags(ssif_info, flags); | ||
748 | ssif_inc_stat(ssif_info, events); | ||
749 | deliver_recv_msg(ssif_info, msg); | ||
750 | } | ||
751 | break; | ||
752 | |||
753 | case SSIF_GETTING_MESSAGES: | ||
754 | if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) { | ||
755 | /* Error getting event, probably done. */ | ||
756 | msg->done(msg); | ||
757 | |||
758 | /* Take off the msg flag. */ | ||
759 | ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL; | ||
760 | handle_flags(ssif_info, flags); | ||
761 | } else if (msg->rsp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 | ||
762 | || msg->rsp[1] != IPMI_GET_MSG_CMD) { | ||
763 | pr_warn(PFX "Invalid response clearing flags: %x %x\n", | ||
764 | msg->rsp[0], msg->rsp[1]); | ||
765 | msg->done(msg); | ||
766 | |||
767 | /* Take off the msg flag. */ | ||
768 | ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL; | ||
769 | handle_flags(ssif_info, flags); | ||
770 | } else { | ||
771 | ssif_inc_stat(ssif_info, incoming_messages); | ||
772 | handle_flags(ssif_info, flags); | ||
773 | deliver_recv_msg(ssif_info, msg); | ||
774 | } | ||
775 | break; | ||
776 | } | ||
777 | |||
778 | flags = ipmi_ssif_lock_cond(ssif_info, &oflags); | ||
779 | if (SSIF_IDLE(ssif_info) && !ssif_info->stopping) { | ||
780 | if (ssif_info->req_events) | ||
781 | start_event_fetch(ssif_info, flags); | ||
782 | else if (ssif_info->req_flags) | ||
783 | start_flag_fetch(ssif_info, flags); | ||
784 | else | ||
785 | start_next_msg(ssif_info, flags); | ||
786 | } else | ||
787 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
788 | |||
789 | if (ssif_info->ssif_debug & SSIF_DEBUG_STATE) | ||
790 | pr_info(PFX "DONE 2: state = %d.\n", ssif_info->ssif_state); | ||
791 | } | ||
792 | |||
793 | static void msg_written_handler(struct ssif_info *ssif_info, int result, | ||
794 | unsigned char *data, unsigned int len) | ||
795 | { | ||
796 | int rv; | ||
797 | |||
798 | /* We are single-threaded here, so no need for a lock. */ | ||
799 | if (result < 0) { | ||
800 | ssif_info->retries_left--; | ||
801 | if (ssif_info->retries_left > 0) { | ||
802 | if (!start_resend(ssif_info)) { | ||
803 | ssif_inc_stat(ssif_info, send_retries); | ||
804 | return; | ||
805 | } | ||
806 | /* request failed, just return the error. */ | ||
807 | ssif_inc_stat(ssif_info, send_errors); | ||
808 | |||
809 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
810 | pr_info(PFX | ||
811 | "Out of retries in msg_written_handler\n"); | ||
812 | msg_done_handler(ssif_info, -EIO, NULL, 0); | ||
813 | return; | ||
814 | } | ||
815 | |||
816 | ssif_inc_stat(ssif_info, send_errors); | ||
817 | |||
818 | /* | ||
819 | * Got an error on transmit, let the done routine | ||
820 | * handle it. | ||
821 | */ | ||
822 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
823 | pr_info("Error in msg_written_handler: %d\n", result); | ||
824 | |||
825 | msg_done_handler(ssif_info, result, NULL, 0); | ||
826 | return; | ||
827 | } | ||
828 | |||
829 | if (ssif_info->multi_data) { | ||
830 | /* In the middle of a multi-data write. */ | ||
831 | int left; | ||
832 | |||
833 | ssif_inc_stat(ssif_info, sent_messages_parts); | ||
834 | |||
835 | left = ssif_info->multi_len - ssif_info->multi_pos; | ||
836 | if (left > 32) | ||
837 | left = 32; | ||
838 | /* Length byte. */ | ||
839 | ssif_info->multi_data[ssif_info->multi_pos] = left; | ||
840 | ssif_info->multi_pos += left; | ||
841 | if (left < 32) | ||
842 | /* | ||
843 | * Write is finished. Note that we must end | ||
844 | * with a write of less than 32 bytes to | ||
845 | * complete the transaction, even if it is | ||
846 | * zero bytes. | ||
847 | */ | ||
848 | ssif_info->multi_data = NULL; | ||
849 | |||
850 | rv = ssif_i2c_send(ssif_info, msg_written_handler, | ||
851 | I2C_SMBUS_WRITE, | ||
852 | SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE, | ||
853 | ssif_info->multi_data + ssif_info->multi_pos, | ||
854 | I2C_SMBUS_BLOCK_DATA); | ||
855 | if (rv < 0) { | ||
856 | /* request failed, just return the error. */ | ||
857 | ssif_inc_stat(ssif_info, send_errors); | ||
858 | |||
859 | if (ssif_info->ssif_debug & SSIF_DEBUG_MSG) | ||
860 | pr_info("Error from i2c_non_blocking_op(3)\n"); | ||
861 | msg_done_handler(ssif_info, -EIO, NULL, 0); | ||
862 | } | ||
863 | } else { | ||
864 | ssif_inc_stat(ssif_info, sent_messages); | ||
865 | ssif_inc_stat(ssif_info, sent_messages_parts); | ||
866 | |||
867 | /* Wait a jiffie then request the next message */ | ||
868 | ssif_info->retries_left = SSIF_RECV_RETRIES; | ||
869 | ssif_info->rtc_us_timer = SSIF_MSG_PART_USEC; | ||
870 | mod_timer(&ssif_info->retry_timer, | ||
871 | jiffies + SSIF_MSG_PART_JIFFIES); | ||
872 | return; | ||
873 | } | ||
874 | } | ||
875 | |||
876 | static int start_resend(struct ssif_info *ssif_info) | ||
877 | { | ||
878 | int rv; | ||
879 | int command; | ||
880 | |||
881 | if (ssif_info->data_len > 32) { | ||
882 | command = SSIF_IPMI_MULTI_PART_REQUEST_START; | ||
883 | ssif_info->multi_data = ssif_info->data; | ||
884 | ssif_info->multi_len = ssif_info->data_len; | ||
885 | /* | ||
886 | * Subtle thing, this is 32, not 33, because we will | ||
887 | * overwrite the thing at position 32 (which was just | ||
888 | * transmitted) with the new length. | ||
889 | */ | ||
890 | ssif_info->multi_pos = 32; | ||
891 | ssif_info->data[0] = 32; | ||
892 | } else { | ||
893 | ssif_info->multi_data = NULL; | ||
894 | command = SSIF_IPMI_REQUEST; | ||
895 | ssif_info->data[0] = ssif_info->data_len; | ||
896 | } | ||
897 | |||
898 | rv = ssif_i2c_send(ssif_info, msg_written_handler, I2C_SMBUS_WRITE, | ||
899 | command, ssif_info->data, I2C_SMBUS_BLOCK_DATA); | ||
900 | if (rv && (ssif_info->ssif_debug & SSIF_DEBUG_MSG)) | ||
901 | pr_info("Error from i2c_non_blocking_op(4)\n"); | ||
902 | return rv; | ||
903 | } | ||
904 | |||
905 | static int start_send(struct ssif_info *ssif_info, | ||
906 | unsigned char *data, | ||
907 | unsigned int len) | ||
908 | { | ||
909 | if (len > IPMI_MAX_MSG_LENGTH) | ||
910 | return -E2BIG; | ||
911 | if (len > ssif_info->max_xmit_msg_size) | ||
912 | return -E2BIG; | ||
913 | |||
914 | ssif_info->retries_left = SSIF_SEND_RETRIES; | ||
915 | memcpy(ssif_info->data+1, data, len); | ||
916 | ssif_info->data_len = len; | ||
917 | return start_resend(ssif_info); | ||
918 | } | ||
919 | |||
920 | /* Must be called with the message lock held. */ | ||
921 | static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags) | ||
922 | { | ||
923 | struct ipmi_smi_msg *msg; | ||
924 | unsigned long oflags; | ||
925 | |||
926 | restart: | ||
927 | if (!SSIF_IDLE(ssif_info)) { | ||
928 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
929 | return; | ||
930 | } | ||
931 | |||
932 | if (!ssif_info->waiting_msg) { | ||
933 | ssif_info->curr_msg = NULL; | ||
934 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
935 | } else { | ||
936 | int rv; | ||
937 | |||
938 | ssif_info->curr_msg = ssif_info->waiting_msg; | ||
939 | ssif_info->waiting_msg = NULL; | ||
940 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
941 | rv = start_send(ssif_info, | ||
942 | ssif_info->curr_msg->data, | ||
943 | ssif_info->curr_msg->data_size); | ||
944 | if (rv) { | ||
945 | msg = ssif_info->curr_msg; | ||
946 | ssif_info->curr_msg = NULL; | ||
947 | return_hosed_msg(ssif_info, msg); | ||
948 | flags = ipmi_ssif_lock_cond(ssif_info, &oflags); | ||
949 | goto restart; | ||
950 | } | ||
951 | } | ||
952 | } | ||
953 | |||
954 | static void sender(void *send_info, | ||
955 | struct ipmi_smi_msg *msg) | ||
956 | { | ||
957 | struct ssif_info *ssif_info = (struct ssif_info *) send_info; | ||
958 | unsigned long oflags, *flags; | ||
959 | |||
960 | BUG_ON(ssif_info->waiting_msg); | ||
961 | ssif_info->waiting_msg = msg; | ||
962 | |||
963 | flags = ipmi_ssif_lock_cond(ssif_info, &oflags); | ||
964 | start_next_msg(ssif_info, flags); | ||
965 | |||
966 | if (ssif_info->ssif_debug & SSIF_DEBUG_TIMING) { | ||
967 | struct timeval t; | ||
968 | |||
969 | do_gettimeofday(&t); | ||
970 | pr_info("**Enqueue %02x %02x: %ld.%6.6ld\n", | ||
971 | msg->data[0], msg->data[1], t.tv_sec, t.tv_usec); | ||
972 | } | ||
973 | } | ||
974 | |||
975 | static int get_smi_info(void *send_info, struct ipmi_smi_info *data) | ||
976 | { | ||
977 | struct ssif_info *ssif_info = send_info; | ||
978 | |||
979 | data->addr_src = ssif_info->addr_source; | ||
980 | data->dev = &ssif_info->client->dev; | ||
981 | data->addr_info = ssif_info->addr_info; | ||
982 | get_device(data->dev); | ||
983 | |||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | /* | ||
988 | * Instead of having our own timer to periodically check the message | ||
989 | * flags, we let the message handler drive us. | ||
990 | */ | ||
991 | static void request_events(void *send_info) | ||
992 | { | ||
993 | struct ssif_info *ssif_info = (struct ssif_info *) send_info; | ||
994 | unsigned long oflags, *flags; | ||
995 | |||
996 | if (!ssif_info->has_event_buffer) | ||
997 | return; | ||
998 | |||
999 | flags = ipmi_ssif_lock_cond(ssif_info, &oflags); | ||
1000 | /* | ||
1001 | * Request flags first, not events, because the lower layer | ||
1002 | * doesn't have a way to send an attention. But make sure | ||
1003 | * event checking still happens. | ||
1004 | */ | ||
1005 | ssif_info->req_events = true; | ||
1006 | if (SSIF_IDLE(ssif_info)) | ||
1007 | start_flag_fetch(ssif_info, flags); | ||
1008 | else { | ||
1009 | ssif_info->req_flags = true; | ||
1010 | ipmi_ssif_unlock_cond(ssif_info, flags); | ||
1011 | } | ||
1012 | } | ||
1013 | |||
1014 | static int inc_usecount(void *send_info) | ||
1015 | { | ||
1016 | struct ssif_info *ssif_info = send_info; | ||
1017 | |||
1018 | if (!i2c_get_adapter(ssif_info->client->adapter->nr)) | ||
1019 | return -ENODEV; | ||
1020 | |||
1021 | i2c_use_client(ssif_info->client); | ||
1022 | return 0; | ||
1023 | } | ||
1024 | |||
1025 | static void dec_usecount(void *send_info) | ||
1026 | { | ||
1027 | struct ssif_info *ssif_info = send_info; | ||
1028 | |||
1029 | i2c_release_client(ssif_info->client); | ||
1030 | i2c_put_adapter(ssif_info->client->adapter); | ||
1031 | } | ||
1032 | |||
1033 | static int ssif_start_processing(void *send_info, | ||
1034 | ipmi_smi_t intf) | ||
1035 | { | ||
1036 | struct ssif_info *ssif_info = send_info; | ||
1037 | |||
1038 | ssif_info->intf = intf; | ||
1039 | |||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | #define MAX_SSIF_BMCS 4 | ||
1044 | |||
1045 | static unsigned short addr[MAX_SSIF_BMCS]; | ||
1046 | static int num_addrs; | ||
1047 | module_param_array(addr, ushort, &num_addrs, 0); | ||
1048 | MODULE_PARM_DESC(addr, "The addresses to scan for IPMI BMCs on the SSIFs."); | ||
1049 | |||
1050 | static char *adapter_name[MAX_SSIF_BMCS]; | ||
1051 | static int num_adapter_names; | ||
1052 | module_param_array(adapter_name, charp, &num_adapter_names, 0); | ||
1053 | MODULE_PARM_DESC(adapter_name, "The string name of the I2C device that has the BMC. By default all devices are scanned."); | ||
1054 | |||
1055 | static int slave_addrs[MAX_SSIF_BMCS]; | ||
1056 | static int num_slave_addrs; | ||
1057 | module_param_array(slave_addrs, int, &num_slave_addrs, 0); | ||
1058 | MODULE_PARM_DESC(slave_addrs, | ||
1059 | "The default IPMB slave address for the controller."); | ||
1060 | |||
1061 | /* | ||
1062 | * Bit 0 enables message debugging, bit 1 enables state debugging, and | ||
1063 | * bit 2 enables timing debugging. This is an array indexed by | ||
1064 | * interface number" | ||
1065 | */ | ||
1066 | static int dbg[MAX_SSIF_BMCS]; | ||
1067 | static int num_dbg; | ||
1068 | module_param_array(dbg, int, &num_dbg, 0); | ||
1069 | MODULE_PARM_DESC(dbg, "Turn on debugging."); | ||
1070 | |||
1071 | static bool ssif_dbg_probe; | ||
1072 | module_param_named(dbg_probe, ssif_dbg_probe, bool, 0); | ||
1073 | MODULE_PARM_DESC(dbg_probe, "Enable debugging of probing of adapters."); | ||
1074 | |||
1075 | static int use_thread; | ||
1076 | module_param(use_thread, int, 0); | ||
1077 | MODULE_PARM_DESC(use_thread, "Use the thread interface."); | ||
1078 | |||
1079 | static bool ssif_tryacpi = 1; | ||
1080 | module_param_named(tryacpi, ssif_tryacpi, bool, 0); | ||
1081 | MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the default scan of the interfaces identified via ACPI"); | ||
1082 | |||
1083 | static bool ssif_trydmi = 1; | ||
1084 | module_param_named(trydmi, ssif_trydmi, bool, 0); | ||
1085 | MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the default scan of the interfaces identified via DMI (SMBIOS)"); | ||
1086 | |||
1087 | static DEFINE_MUTEX(ssif_infos_mutex); | ||
1088 | static LIST_HEAD(ssif_infos); | ||
1089 | |||
1090 | static int ssif_remove(struct i2c_client *client) | ||
1091 | { | ||
1092 | struct ssif_info *ssif_info = i2c_get_clientdata(client); | ||
1093 | int rv; | ||
1094 | |||
1095 | if (!ssif_info) | ||
1096 | return 0; | ||
1097 | |||
1098 | i2c_set_clientdata(client, NULL); | ||
1099 | |||
1100 | /* | ||
1101 | * After this point, we won't deliver anything asychronously | ||
1102 | * to the message handler. We can unregister ourself. | ||
1103 | */ | ||
1104 | rv = ipmi_unregister_smi(ssif_info->intf); | ||
1105 | if (rv) { | ||
1106 | pr_err(PFX "Unable to unregister device: errno=%d\n", rv); | ||
1107 | return rv; | ||
1108 | } | ||
1109 | ssif_info->intf = NULL; | ||
1110 | |||
1111 | /* make sure the driver is not looking for flags any more. */ | ||
1112 | while (ssif_info->ssif_state != SSIF_NORMAL) | ||
1113 | schedule_timeout(1); | ||
1114 | |||
1115 | ssif_info->stopping = true; | ||
1116 | del_timer_sync(&ssif_info->retry_timer); | ||
1117 | if (ssif_info->thread) { | ||
1118 | complete(&ssif_info->wake_thread); | ||
1119 | kthread_stop(ssif_info->thread); | ||
1120 | } | ||
1121 | |||
1122 | /* | ||
1123 | * No message can be outstanding now, we have removed the | ||
1124 | * upper layer and it permitted us to do so. | ||
1125 | */ | ||
1126 | kfree(ssif_info); | ||
1127 | return 0; | ||
1128 | } | ||
1129 | |||
1130 | static int do_cmd(struct i2c_client *client, int len, unsigned char *msg, | ||
1131 | int *resp_len, unsigned char *resp) | ||
1132 | { | ||
1133 | int retry_cnt; | ||
1134 | int ret; | ||
1135 | |||
1136 | retry_cnt = SSIF_SEND_RETRIES; | ||
1137 | retry1: | ||
1138 | ret = i2c_smbus_write_block_data(client, SSIF_IPMI_REQUEST, len, msg); | ||
1139 | if (ret) { | ||
1140 | retry_cnt--; | ||
1141 | if (retry_cnt > 0) | ||
1142 | goto retry1; | ||
1143 | return -ENODEV; | ||
1144 | } | ||
1145 | |||
1146 | ret = -ENODEV; | ||
1147 | retry_cnt = SSIF_RECV_RETRIES; | ||
1148 | while (retry_cnt > 0) { | ||
1149 | ret = i2c_smbus_read_block_data(client, SSIF_IPMI_RESPONSE, | ||
1150 | resp); | ||
1151 | if (ret > 0) | ||
1152 | break; | ||
1153 | msleep(SSIF_MSG_MSEC); | ||
1154 | retry_cnt--; | ||
1155 | if (retry_cnt <= 0) | ||
1156 | break; | ||
1157 | } | ||
1158 | |||
1159 | if (ret > 0) { | ||
1160 | /* Validate that the response is correct. */ | ||
1161 | if (ret < 3 || | ||
1162 | (resp[0] != (msg[0] | (1 << 2))) || | ||
1163 | (resp[1] != msg[1])) | ||
1164 | ret = -EINVAL; | ||
1165 | else { | ||
1166 | *resp_len = ret; | ||
1167 | ret = 0; | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1171 | return ret; | ||
1172 | } | ||
1173 | |||
1174 | static int ssif_detect(struct i2c_client *client, struct i2c_board_info *info) | ||
1175 | { | ||
1176 | unsigned char *resp; | ||
1177 | unsigned char msg[3]; | ||
1178 | int rv; | ||
1179 | int len; | ||
1180 | |||
1181 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | ||
1182 | if (!resp) | ||
1183 | return -ENOMEM; | ||
1184 | |||
1185 | /* Do a Get Device ID command, since it is required. */ | ||
1186 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
1187 | msg[1] = IPMI_GET_DEVICE_ID_CMD; | ||
1188 | rv = do_cmd(client, 2, msg, &len, resp); | ||
1189 | if (rv) | ||
1190 | rv = -ENODEV; | ||
1191 | else | ||
1192 | strlcpy(info->type, DEVICE_NAME, I2C_NAME_SIZE); | ||
1193 | kfree(resp); | ||
1194 | return rv; | ||
1195 | } | ||
1196 | |||
1197 | static int smi_type_proc_show(struct seq_file *m, void *v) | ||
1198 | { | ||
1199 | return seq_puts(m, "ssif\n"); | ||
1200 | } | ||
1201 | |||
1202 | static int smi_type_proc_open(struct inode *inode, struct file *file) | ||
1203 | { | ||
1204 | return single_open(file, smi_type_proc_show, inode->i_private); | ||
1205 | } | ||
1206 | |||
1207 | static const struct file_operations smi_type_proc_ops = { | ||
1208 | .open = smi_type_proc_open, | ||
1209 | .read = seq_read, | ||
1210 | .llseek = seq_lseek, | ||
1211 | .release = single_release, | ||
1212 | }; | ||
1213 | |||
1214 | static int smi_stats_proc_show(struct seq_file *m, void *v) | ||
1215 | { | ||
1216 | struct ssif_info *ssif_info = m->private; | ||
1217 | |||
1218 | seq_printf(m, "sent_messages: %u\n", | ||
1219 | ssif_get_stat(ssif_info, sent_messages)); | ||
1220 | seq_printf(m, "sent_messages_parts: %u\n", | ||
1221 | ssif_get_stat(ssif_info, sent_messages_parts)); | ||
1222 | seq_printf(m, "send_retries: %u\n", | ||
1223 | ssif_get_stat(ssif_info, send_retries)); | ||
1224 | seq_printf(m, "send_errors: %u\n", | ||
1225 | ssif_get_stat(ssif_info, send_errors)); | ||
1226 | seq_printf(m, "received_messages: %u\n", | ||
1227 | ssif_get_stat(ssif_info, received_messages)); | ||
1228 | seq_printf(m, "received_message_parts: %u\n", | ||
1229 | ssif_get_stat(ssif_info, received_message_parts)); | ||
1230 | seq_printf(m, "receive_retries: %u\n", | ||
1231 | ssif_get_stat(ssif_info, receive_retries)); | ||
1232 | seq_printf(m, "receive_errors: %u\n", | ||
1233 | ssif_get_stat(ssif_info, receive_errors)); | ||
1234 | seq_printf(m, "flag_fetches: %u\n", | ||
1235 | ssif_get_stat(ssif_info, flag_fetches)); | ||
1236 | seq_printf(m, "hosed: %u\n", | ||
1237 | ssif_get_stat(ssif_info, hosed)); | ||
1238 | seq_printf(m, "events: %u\n", | ||
1239 | ssif_get_stat(ssif_info, events)); | ||
1240 | seq_printf(m, "watchdog_pretimeouts: %u\n", | ||
1241 | ssif_get_stat(ssif_info, watchdog_pretimeouts)); | ||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | static int smi_stats_proc_open(struct inode *inode, struct file *file) | ||
1246 | { | ||
1247 | return single_open(file, smi_stats_proc_show, PDE_DATA(inode)); | ||
1248 | } | ||
1249 | |||
1250 | static const struct file_operations smi_stats_proc_ops = { | ||
1251 | .open = smi_stats_proc_open, | ||
1252 | .read = seq_read, | ||
1253 | .llseek = seq_lseek, | ||
1254 | .release = single_release, | ||
1255 | }; | ||
1256 | |||
1257 | static struct ssif_addr_info *ssif_info_find(unsigned short addr, | ||
1258 | char *adapter_name, | ||
1259 | bool match_null_name) | ||
1260 | { | ||
1261 | struct ssif_addr_info *info, *found = NULL; | ||
1262 | |||
1263 | restart: | ||
1264 | list_for_each_entry(info, &ssif_infos, link) { | ||
1265 | if (info->binfo.addr == addr) { | ||
1266 | if (info->adapter_name || adapter_name) { | ||
1267 | if (!info->adapter_name != !adapter_name) { | ||
1268 | /* One is NULL and one is not */ | ||
1269 | continue; | ||
1270 | } | ||
1271 | if (strcmp(info->adapter_name, adapter_name)) | ||
1272 | /* Names to not match */ | ||
1273 | continue; | ||
1274 | } | ||
1275 | found = info; | ||
1276 | break; | ||
1277 | } | ||
1278 | } | ||
1279 | |||
1280 | if (!found && match_null_name) { | ||
1281 | /* Try to get an exact match first, then try with a NULL name */ | ||
1282 | adapter_name = NULL; | ||
1283 | match_null_name = false; | ||
1284 | goto restart; | ||
1285 | } | ||
1286 | |||
1287 | return found; | ||
1288 | } | ||
1289 | |||
1290 | static bool check_acpi(struct ssif_info *ssif_info, struct device *dev) | ||
1291 | { | ||
1292 | #ifdef CONFIG_ACPI | ||
1293 | acpi_handle acpi_handle; | ||
1294 | |||
1295 | acpi_handle = ACPI_HANDLE(dev); | ||
1296 | if (acpi_handle) { | ||
1297 | ssif_info->addr_source = SI_ACPI; | ||
1298 | ssif_info->addr_info.acpi_info.acpi_handle = acpi_handle; | ||
1299 | return true; | ||
1300 | } | ||
1301 | #endif | ||
1302 | return false; | ||
1303 | } | ||
1304 | |||
1305 | static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
1306 | { | ||
1307 | unsigned char msg[3]; | ||
1308 | unsigned char *resp; | ||
1309 | struct ssif_info *ssif_info; | ||
1310 | int rv = 0; | ||
1311 | int len; | ||
1312 | int i; | ||
1313 | u8 slave_addr = 0; | ||
1314 | struct ssif_addr_info *addr_info = NULL; | ||
1315 | |||
1316 | |||
1317 | resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL); | ||
1318 | if (!resp) | ||
1319 | return -ENOMEM; | ||
1320 | |||
1321 | ssif_info = kzalloc(sizeof(*ssif_info), GFP_KERNEL); | ||
1322 | if (!ssif_info) { | ||
1323 | kfree(resp); | ||
1324 | return -ENOMEM; | ||
1325 | } | ||
1326 | |||
1327 | if (!check_acpi(ssif_info, &client->dev)) { | ||
1328 | addr_info = ssif_info_find(client->addr, client->adapter->name, | ||
1329 | true); | ||
1330 | if (!addr_info) { | ||
1331 | /* Must have come in through sysfs. */ | ||
1332 | ssif_info->addr_source = SI_HOTMOD; | ||
1333 | } else { | ||
1334 | ssif_info->addr_source = addr_info->addr_src; | ||
1335 | ssif_info->ssif_debug = addr_info->debug; | ||
1336 | ssif_info->addr_info = addr_info->addr_info; | ||
1337 | slave_addr = addr_info->slave_addr; | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | pr_info(PFX "Trying %s-specified SSIF interface at i2c address 0x%x, adapter %s, slave address 0x%x\n", | ||
1342 | ipmi_addr_src_to_str(ssif_info->addr_source), | ||
1343 | client->addr, client->adapter->name, slave_addr); | ||
1344 | |||
1345 | /* | ||
1346 | * Do a Get Device ID command, since it comes back with some | ||
1347 | * useful info. | ||
1348 | */ | ||
1349 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
1350 | msg[1] = IPMI_GET_DEVICE_ID_CMD; | ||
1351 | rv = do_cmd(client, 2, msg, &len, resp); | ||
1352 | if (rv) | ||
1353 | goto out; | ||
1354 | |||
1355 | rv = ipmi_demangle_device_id(resp, len, &ssif_info->device_id); | ||
1356 | if (rv) | ||
1357 | goto out; | ||
1358 | |||
1359 | ssif_info->client = client; | ||
1360 | i2c_set_clientdata(client, ssif_info); | ||
1361 | |||
1362 | /* Now check for system interface capabilities */ | ||
1363 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
1364 | msg[1] = IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD; | ||
1365 | msg[2] = 0; /* SSIF */ | ||
1366 | rv = do_cmd(client, 3, msg, &len, resp); | ||
1367 | if (!rv && (len >= 3) && (resp[2] == 0)) { | ||
1368 | if (len < 7) { | ||
1369 | if (ssif_dbg_probe) | ||
1370 | pr_info(PFX "SSIF info too short: %d\n", len); | ||
1371 | goto no_support; | ||
1372 | } | ||
1373 | |||
1374 | /* Got a good SSIF response, handle it. */ | ||
1375 | ssif_info->max_xmit_msg_size = resp[5]; | ||
1376 | ssif_info->max_recv_msg_size = resp[6]; | ||
1377 | ssif_info->multi_support = (resp[4] >> 6) & 0x3; | ||
1378 | ssif_info->supports_pec = (resp[4] >> 3) & 0x1; | ||
1379 | |||
1380 | /* Sanitize the data */ | ||
1381 | switch (ssif_info->multi_support) { | ||
1382 | case SSIF_NO_MULTI: | ||
1383 | if (ssif_info->max_xmit_msg_size > 32) | ||
1384 | ssif_info->max_xmit_msg_size = 32; | ||
1385 | if (ssif_info->max_recv_msg_size > 32) | ||
1386 | ssif_info->max_recv_msg_size = 32; | ||
1387 | break; | ||
1388 | |||
1389 | case SSIF_MULTI_2_PART: | ||
1390 | if (ssif_info->max_xmit_msg_size > 64) | ||
1391 | ssif_info->max_xmit_msg_size = 64; | ||
1392 | if (ssif_info->max_recv_msg_size > 62) | ||
1393 | ssif_info->max_recv_msg_size = 62; | ||
1394 | break; | ||
1395 | |||
1396 | case SSIF_MULTI_n_PART: | ||
1397 | break; | ||
1398 | |||
1399 | default: | ||
1400 | /* Data is not sane, just give up. */ | ||
1401 | goto no_support; | ||
1402 | } | ||
1403 | } else { | ||
1404 | no_support: | ||
1405 | /* Assume no multi-part or PEC support */ | ||
1406 | pr_info(PFX "Error fetching SSIF: %d %d %2.2x, your system probably doesn't support this command so using defaults\n", | ||
1407 | rv, len, resp[2]); | ||
1408 | |||
1409 | ssif_info->max_xmit_msg_size = 32; | ||
1410 | ssif_info->max_recv_msg_size = 32; | ||
1411 | ssif_info->multi_support = SSIF_NO_MULTI; | ||
1412 | ssif_info->supports_pec = 0; | ||
1413 | } | ||
1414 | |||
1415 | /* Make sure the NMI timeout is cleared. */ | ||
1416 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
1417 | msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD; | ||
1418 | msg[2] = WDT_PRE_TIMEOUT_INT; | ||
1419 | rv = do_cmd(client, 3, msg, &len, resp); | ||
1420 | if (rv || (len < 3) || (resp[2] != 0)) | ||
1421 | pr_warn(PFX "Unable to clear message flags: %d %d %2.2x\n", | ||
1422 | rv, len, resp[2]); | ||
1423 | |||
1424 | /* Attempt to enable the event buffer. */ | ||
1425 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
1426 | msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD; | ||
1427 | rv = do_cmd(client, 2, msg, &len, resp); | ||
1428 | if (rv || (len < 4) || (resp[2] != 0)) { | ||
1429 | pr_warn(PFX "Error getting global enables: %d %d %2.2x\n", | ||
1430 | rv, len, resp[2]); | ||
1431 | rv = 0; /* Not fatal */ | ||
1432 | goto found; | ||
1433 | } | ||
1434 | |||
1435 | if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) { | ||
1436 | ssif_info->has_event_buffer = true; | ||
1437 | /* buffer is already enabled, nothing to do. */ | ||
1438 | goto found; | ||
1439 | } | ||
1440 | |||
1441 | msg[0] = IPMI_NETFN_APP_REQUEST << 2; | ||
1442 | msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD; | ||
1443 | msg[2] = resp[3] | IPMI_BMC_EVT_MSG_BUFF; | ||
1444 | rv = do_cmd(client, 3, msg, &len, resp); | ||
1445 | if (rv || (len < 2)) { | ||
1446 | pr_warn(PFX "Error getting global enables: %d %d %2.2x\n", | ||
1447 | rv, len, resp[2]); | ||
1448 | rv = 0; /* Not fatal */ | ||
1449 | goto found; | ||
1450 | } | ||
1451 | |||
1452 | if (resp[2] == 0) | ||
1453 | /* A successful return means the event buffer is supported. */ | ||
1454 | ssif_info->has_event_buffer = true; | ||
1455 | |||
1456 | found: | ||
1457 | ssif_info->intf_num = atomic_inc_return(&next_intf); | ||
1458 | |||
1459 | if (ssif_dbg_probe) { | ||
1460 | pr_info("ssif_probe: i2c_probe found device at i2c address %x\n", | ||
1461 | client->addr); | ||
1462 | } | ||
1463 | |||
1464 | spin_lock_init(&ssif_info->lock); | ||
1465 | ssif_info->ssif_state = SSIF_NORMAL; | ||
1466 | init_timer(&ssif_info->retry_timer); | ||
1467 | ssif_info->retry_timer.data = (unsigned long) ssif_info; | ||
1468 | ssif_info->retry_timer.function = retry_timeout; | ||
1469 | |||
1470 | for (i = 0; i < SSIF_NUM_STATS; i++) | ||
1471 | atomic_set(&ssif_info->stats[i], 0); | ||
1472 | |||
1473 | if (ssif_info->supports_pec) | ||
1474 | ssif_info->client->flags |= I2C_CLIENT_PEC; | ||
1475 | |||
1476 | ssif_info->handlers.owner = THIS_MODULE; | ||
1477 | ssif_info->handlers.start_processing = ssif_start_processing; | ||
1478 | ssif_info->handlers.get_smi_info = get_smi_info; | ||
1479 | ssif_info->handlers.sender = sender; | ||
1480 | ssif_info->handlers.request_events = request_events; | ||
1481 | ssif_info->handlers.inc_usecount = inc_usecount; | ||
1482 | ssif_info->handlers.dec_usecount = dec_usecount; | ||
1483 | |||
1484 | { | ||
1485 | unsigned int thread_num; | ||
1486 | |||
1487 | thread_num = ((ssif_info->client->adapter->nr << 8) | | ||
1488 | ssif_info->client->addr); | ||
1489 | init_completion(&ssif_info->wake_thread); | ||
1490 | ssif_info->thread = kthread_run(ipmi_ssif_thread, ssif_info, | ||
1491 | "kssif%4.4x", thread_num); | ||
1492 | if (IS_ERR(ssif_info->thread)) { | ||
1493 | rv = PTR_ERR(ssif_info->thread); | ||
1494 | dev_notice(&ssif_info->client->dev, | ||
1495 | "Could not start kernel thread: error %d\n", | ||
1496 | rv); | ||
1497 | goto out; | ||
1498 | } | ||
1499 | } | ||
1500 | |||
1501 | rv = ipmi_register_smi(&ssif_info->handlers, | ||
1502 | ssif_info, | ||
1503 | &ssif_info->device_id, | ||
1504 | &ssif_info->client->dev, | ||
1505 | slave_addr); | ||
1506 | if (rv) { | ||
1507 | pr_err(PFX "Unable to register device: error %d\n", rv); | ||
1508 | goto out; | ||
1509 | } | ||
1510 | |||
1511 | rv = ipmi_smi_add_proc_entry(ssif_info->intf, "type", | ||
1512 | &smi_type_proc_ops, | ||
1513 | ssif_info); | ||
1514 | if (rv) { | ||
1515 | pr_err(PFX "Unable to create proc entry: %d\n", rv); | ||
1516 | goto out_err_unreg; | ||
1517 | } | ||
1518 | |||
1519 | rv = ipmi_smi_add_proc_entry(ssif_info->intf, "ssif_stats", | ||
1520 | &smi_stats_proc_ops, | ||
1521 | ssif_info); | ||
1522 | if (rv) { | ||
1523 | pr_err(PFX "Unable to create proc entry: %d\n", rv); | ||
1524 | goto out_err_unreg; | ||
1525 | } | ||
1526 | |||
1527 | out: | ||
1528 | if (rv) | ||
1529 | kfree(ssif_info); | ||
1530 | kfree(resp); | ||
1531 | return rv; | ||
1532 | |||
1533 | out_err_unreg: | ||
1534 | ipmi_unregister_smi(ssif_info->intf); | ||
1535 | goto out; | ||
1536 | } | ||
1537 | |||
1538 | static int ssif_adapter_handler(struct device *adev, void *opaque) | ||
1539 | { | ||
1540 | struct ssif_addr_info *addr_info = opaque; | ||
1541 | |||
1542 | if (adev->type != &i2c_adapter_type) | ||
1543 | return 0; | ||
1544 | |||
1545 | i2c_new_device(to_i2c_adapter(adev), &addr_info->binfo); | ||
1546 | |||
1547 | if (!addr_info->adapter_name) | ||
1548 | return 1; /* Only try the first I2C adapter by default. */ | ||
1549 | return 0; | ||
1550 | } | ||
1551 | |||
1552 | static int new_ssif_client(int addr, char *adapter_name, | ||
1553 | int debug, int slave_addr, | ||
1554 | enum ipmi_addr_src addr_src) | ||
1555 | { | ||
1556 | struct ssif_addr_info *addr_info; | ||
1557 | int rv = 0; | ||
1558 | |||
1559 | mutex_lock(&ssif_infos_mutex); | ||
1560 | if (ssif_info_find(addr, adapter_name, false)) { | ||
1561 | rv = -EEXIST; | ||
1562 | goto out_unlock; | ||
1563 | } | ||
1564 | |||
1565 | addr_info = kzalloc(sizeof(*addr_info), GFP_KERNEL); | ||
1566 | if (!addr_info) { | ||
1567 | rv = -ENOMEM; | ||
1568 | goto out_unlock; | ||
1569 | } | ||
1570 | |||
1571 | if (adapter_name) { | ||
1572 | addr_info->adapter_name = kstrdup(adapter_name, GFP_KERNEL); | ||
1573 | if (!addr_info->adapter_name) { | ||
1574 | kfree(addr_info); | ||
1575 | rv = -ENOMEM; | ||
1576 | goto out_unlock; | ||
1577 | } | ||
1578 | } | ||
1579 | |||
1580 | strncpy(addr_info->binfo.type, DEVICE_NAME, | ||
1581 | sizeof(addr_info->binfo.type)); | ||
1582 | addr_info->binfo.addr = addr; | ||
1583 | addr_info->binfo.platform_data = addr_info; | ||
1584 | addr_info->debug = debug; | ||
1585 | addr_info->slave_addr = slave_addr; | ||
1586 | addr_info->addr_src = addr_src; | ||
1587 | |||
1588 | list_add_tail(&addr_info->link, &ssif_infos); | ||
1589 | |||
1590 | if (initialized) | ||
1591 | i2c_for_each_dev(addr_info, ssif_adapter_handler); | ||
1592 | /* Otherwise address list will get it */ | ||
1593 | |||
1594 | out_unlock: | ||
1595 | mutex_unlock(&ssif_infos_mutex); | ||
1596 | return rv; | ||
1597 | } | ||
1598 | |||
1599 | static void free_ssif_clients(void) | ||
1600 | { | ||
1601 | struct ssif_addr_info *info, *tmp; | ||
1602 | |||
1603 | mutex_lock(&ssif_infos_mutex); | ||
1604 | list_for_each_entry_safe(info, tmp, &ssif_infos, link) { | ||
1605 | list_del(&info->link); | ||
1606 | kfree(info->adapter_name); | ||
1607 | kfree(info); | ||
1608 | } | ||
1609 | mutex_unlock(&ssif_infos_mutex); | ||
1610 | } | ||
1611 | |||
1612 | static unsigned short *ssif_address_list(void) | ||
1613 | { | ||
1614 | struct ssif_addr_info *info; | ||
1615 | unsigned int count = 0, i; | ||
1616 | unsigned short *address_list; | ||
1617 | |||
1618 | list_for_each_entry(info, &ssif_infos, link) | ||
1619 | count++; | ||
1620 | |||
1621 | address_list = kzalloc(sizeof(*address_list) * (count + 1), GFP_KERNEL); | ||
1622 | if (!address_list) | ||
1623 | return NULL; | ||
1624 | |||
1625 | i = 0; | ||
1626 | list_for_each_entry(info, &ssif_infos, link) { | ||
1627 | unsigned short addr = info->binfo.addr; | ||
1628 | int j; | ||
1629 | |||
1630 | for (j = 0; j < i; j++) { | ||
1631 | if (address_list[j] == addr) | ||
1632 | goto skip_addr; | ||
1633 | } | ||
1634 | address_list[i] = addr; | ||
1635 | skip_addr: | ||
1636 | i++; | ||
1637 | } | ||
1638 | address_list[i] = I2C_CLIENT_END; | ||
1639 | |||
1640 | return address_list; | ||
1641 | } | ||
1642 | |||
1643 | #ifdef CONFIG_ACPI | ||
1644 | static struct acpi_device_id ssif_acpi_match[] = { | ||
1645 | { "IPI0001", 0 }, | ||
1646 | { }, | ||
1647 | }; | ||
1648 | MODULE_DEVICE_TABLE(acpi, ssif_acpi_match); | ||
1649 | |||
1650 | /* | ||
1651 | * Once we get an ACPI failure, we don't try any more, because we go | ||
1652 | * through the tables sequentially. Once we don't find a table, there | ||
1653 | * are no more. | ||
1654 | */ | ||
1655 | static int acpi_failure; | ||
1656 | |||
1657 | /* | ||
1658 | * Defined in the IPMI 2.0 spec. | ||
1659 | */ | ||
1660 | struct SPMITable { | ||
1661 | s8 Signature[4]; | ||
1662 | u32 Length; | ||
1663 | u8 Revision; | ||
1664 | u8 Checksum; | ||
1665 | s8 OEMID[6]; | ||
1666 | s8 OEMTableID[8]; | ||
1667 | s8 OEMRevision[4]; | ||
1668 | s8 CreatorID[4]; | ||
1669 | s8 CreatorRevision[4]; | ||
1670 | u8 InterfaceType; | ||
1671 | u8 IPMIlegacy; | ||
1672 | s16 SpecificationRevision; | ||
1673 | |||
1674 | /* | ||
1675 | * Bit 0 - SCI interrupt supported | ||
1676 | * Bit 1 - I/O APIC/SAPIC | ||
1677 | */ | ||
1678 | u8 InterruptType; | ||
1679 | |||
1680 | /* | ||
1681 | * If bit 0 of InterruptType is set, then this is the SCI | ||
1682 | * interrupt in the GPEx_STS register. | ||
1683 | */ | ||
1684 | u8 GPE; | ||
1685 | |||
1686 | s16 Reserved; | ||
1687 | |||
1688 | /* | ||
1689 | * If bit 1 of InterruptType is set, then this is the I/O | ||
1690 | * APIC/SAPIC interrupt. | ||
1691 | */ | ||
1692 | u32 GlobalSystemInterrupt; | ||
1693 | |||
1694 | /* The actual register address. */ | ||
1695 | struct acpi_generic_address addr; | ||
1696 | |||
1697 | u8 UID[4]; | ||
1698 | |||
1699 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ | ||
1700 | }; | ||
1701 | |||
1702 | static int try_init_spmi(struct SPMITable *spmi) | ||
1703 | { | ||
1704 | unsigned short myaddr; | ||
1705 | |||
1706 | if (num_addrs >= MAX_SSIF_BMCS) | ||
1707 | return -1; | ||
1708 | |||
1709 | if (spmi->IPMIlegacy != 1) { | ||
1710 | pr_warn("IPMI: Bad SPMI legacy: %d\n", spmi->IPMIlegacy); | ||
1711 | return -ENODEV; | ||
1712 | } | ||
1713 | |||
1714 | if (spmi->InterfaceType != 4) | ||
1715 | return -ENODEV; | ||
1716 | |||
1717 | if (spmi->addr.space_id != ACPI_ADR_SPACE_SMBUS) { | ||
1718 | pr_warn(PFX "Invalid ACPI SSIF I/O Address type: %d\n", | ||
1719 | spmi->addr.space_id); | ||
1720 | return -EIO; | ||
1721 | } | ||
1722 | |||
1723 | myaddr = spmi->addr.address >> 1; | ||
1724 | |||
1725 | return new_ssif_client(myaddr, NULL, 0, 0, SI_SPMI); | ||
1726 | } | ||
1727 | |||
1728 | static void spmi_find_bmc(void) | ||
1729 | { | ||
1730 | acpi_status status; | ||
1731 | struct SPMITable *spmi; | ||
1732 | int i; | ||
1733 | |||
1734 | if (acpi_disabled) | ||
1735 | return; | ||
1736 | |||
1737 | if (acpi_failure) | ||
1738 | return; | ||
1739 | |||
1740 | for (i = 0; ; i++) { | ||
1741 | status = acpi_get_table(ACPI_SIG_SPMI, i+1, | ||
1742 | (struct acpi_table_header **)&spmi); | ||
1743 | if (status != AE_OK) | ||
1744 | return; | ||
1745 | |||
1746 | try_init_spmi(spmi); | ||
1747 | } | ||
1748 | } | ||
1749 | #else | ||
1750 | static void spmi_find_bmc(void) { } | ||
1751 | #endif | ||
1752 | |||
1753 | #ifdef CONFIG_DMI | ||
1754 | static int decode_dmi(const struct dmi_device *dmi_dev) | ||
1755 | { | ||
1756 | struct dmi_header *dm = dmi_dev->device_data; | ||
1757 | u8 *data = (u8 *) dm; | ||
1758 | u8 len = dm->length; | ||
1759 | unsigned short myaddr; | ||
1760 | int slave_addr; | ||
1761 | |||
1762 | if (num_addrs >= MAX_SSIF_BMCS) | ||
1763 | return -1; | ||
1764 | |||
1765 | if (len < 9) | ||
1766 | return -1; | ||
1767 | |||
1768 | if (data[0x04] != 4) /* Not SSIF */ | ||
1769 | return -1; | ||
1770 | |||
1771 | if ((data[8] >> 1) == 0) { | ||
1772 | /* | ||
1773 | * Some broken systems put the I2C address in | ||
1774 | * the slave address field. We try to | ||
1775 | * accommodate them here. | ||
1776 | */ | ||
1777 | myaddr = data[6] >> 1; | ||
1778 | slave_addr = 0; | ||
1779 | } else { | ||
1780 | myaddr = data[8] >> 1; | ||
1781 | slave_addr = data[6]; | ||
1782 | } | ||
1783 | |||
1784 | return new_ssif_client(myaddr, NULL, 0, 0, SI_SMBIOS); | ||
1785 | } | ||
1786 | |||
1787 | static void dmi_iterator(void) | ||
1788 | { | ||
1789 | const struct dmi_device *dev = NULL; | ||
1790 | |||
1791 | while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) | ||
1792 | decode_dmi(dev); | ||
1793 | } | ||
1794 | #else | ||
1795 | static void dmi_iterator(void) { } | ||
1796 | #endif | ||
1797 | |||
1798 | static const struct i2c_device_id ssif_id[] = { | ||
1799 | { DEVICE_NAME, 0 }, | ||
1800 | { } | ||
1801 | }; | ||
1802 | MODULE_DEVICE_TABLE(i2c, ssif_id); | ||
1803 | |||
1804 | static struct i2c_driver ssif_i2c_driver = { | ||
1805 | .class = I2C_CLASS_HWMON, | ||
1806 | .driver = { | ||
1807 | .owner = THIS_MODULE, | ||
1808 | .name = DEVICE_NAME | ||
1809 | }, | ||
1810 | .probe = ssif_probe, | ||
1811 | .remove = ssif_remove, | ||
1812 | .id_table = ssif_id, | ||
1813 | .detect = ssif_detect | ||
1814 | }; | ||
1815 | |||
1816 | static int init_ipmi_ssif(void) | ||
1817 | { | ||
1818 | int i; | ||
1819 | int rv; | ||
1820 | |||
1821 | if (initialized) | ||
1822 | return 0; | ||
1823 | |||
1824 | pr_info("IPMI SSIF Interface driver\n"); | ||
1825 | |||
1826 | /* build list for i2c from addr list */ | ||
1827 | for (i = 0; i < num_addrs; i++) { | ||
1828 | rv = new_ssif_client(addr[i], adapter_name[i], | ||
1829 | dbg[i], slave_addrs[i], | ||
1830 | SI_HARDCODED); | ||
1831 | if (!rv) | ||
1832 | pr_err(PFX | ||
1833 | "Couldn't add hardcoded device at addr 0x%x\n", | ||
1834 | addr[i]); | ||
1835 | } | ||
1836 | |||
1837 | if (ssif_tryacpi) | ||
1838 | ssif_i2c_driver.driver.acpi_match_table = | ||
1839 | ACPI_PTR(ssif_acpi_match); | ||
1840 | if (ssif_trydmi) | ||
1841 | dmi_iterator(); | ||
1842 | if (ssif_tryacpi) | ||
1843 | spmi_find_bmc(); | ||
1844 | |||
1845 | ssif_i2c_driver.address_list = ssif_address_list(); | ||
1846 | |||
1847 | rv = i2c_add_driver(&ssif_i2c_driver); | ||
1848 | if (!rv) | ||
1849 | initialized = true; | ||
1850 | |||
1851 | return rv; | ||
1852 | } | ||
1853 | module_init(init_ipmi_ssif); | ||
1854 | |||
1855 | static void cleanup_ipmi_ssif(void) | ||
1856 | { | ||
1857 | if (!initialized) | ||
1858 | return; | ||
1859 | |||
1860 | initialized = false; | ||
1861 | |||
1862 | i2c_del_driver(&ssif_i2c_driver); | ||
1863 | |||
1864 | free_ssif_clients(); | ||
1865 | } | ||
1866 | module_exit(cleanup_ipmi_ssif); | ||
1867 | |||
1868 | MODULE_AUTHOR("Todd C Davis <todd.c.davis@intel.com>, Corey Minyard <minyard@acm.org>"); | ||
1869 | MODULE_DESCRIPTION("IPMI driver for management controllers on a SMBus"); | ||
1870 | MODULE_LICENSE("GPL"); | ||
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 76d2acbfa7c6..838dbfa3c331 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | #include <linux/list.h> | 38 | #include <linux/list.h> |
39 | #include <linux/proc_fs.h> | 39 | #include <linux/proc_fs.h> |
40 | #include <linux/acpi.h> /* For acpi_handle */ | ||
40 | 41 | ||
41 | struct module; | 42 | struct module; |
42 | struct device; | 43 | struct device; |
@@ -278,15 +279,18 @@ enum ipmi_addr_src { | |||
278 | SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS, | 279 | SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS, |
279 | SI_PCI, SI_DEVICETREE, SI_DEFAULT | 280 | SI_PCI, SI_DEVICETREE, SI_DEFAULT |
280 | }; | 281 | }; |
282 | const char *ipmi_addr_src_to_str(enum ipmi_addr_src src); | ||
281 | 283 | ||
282 | union ipmi_smi_info_union { | 284 | union ipmi_smi_info_union { |
285 | #ifdef CONFIG_ACPI | ||
283 | /* | 286 | /* |
284 | * the acpi_info element is defined for the SI_ACPI | 287 | * the acpi_info element is defined for the SI_ACPI |
285 | * address type | 288 | * address type |
286 | */ | 289 | */ |
287 | struct { | 290 | struct { |
288 | void *acpi_handle; | 291 | acpi_handle acpi_handle; |
289 | } acpi_info; | 292 | } acpi_info; |
293 | #endif | ||
290 | }; | 294 | }; |
291 | 295 | ||
292 | struct ipmi_smi_info { | 296 | struct ipmi_smi_info { |
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index bd349240d50e..0b1e569f5ff5 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h | |||
@@ -98,12 +98,11 @@ struct ipmi_smi_handlers { | |||
98 | operation is not allowed to fail. If an error occurs, it | 98 | operation is not allowed to fail. If an error occurs, it |
99 | should report back the error in a received message. It may | 99 | should report back the error in a received message. It may |
100 | do this in the current call context, since no write locks | 100 | do this in the current call context, since no write locks |
101 | are held when this is run. If the priority is > 0, the | 101 | are held when this is run. Message are delivered one at |
102 | message will go into a high-priority queue and be sent | 102 | a time by the message handler, a new message will not be |
103 | first. Otherwise, it goes into a normal-priority queue. */ | 103 | delivered until the previous message is returned. */ |
104 | void (*sender)(void *send_info, | 104 | void (*sender)(void *send_info, |
105 | struct ipmi_smi_msg *msg, | 105 | struct ipmi_smi_msg *msg); |
106 | int priority); | ||
107 | 106 | ||
108 | /* Called by the upper layer to request that we try to get | 107 | /* Called by the upper layer to request that we try to get |
109 | events from the BMC we are attached to. */ | 108 | events from the BMC we are attached to. */ |
@@ -212,7 +211,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
212 | void *send_info, | 211 | void *send_info, |
213 | struct ipmi_device_id *device_id, | 212 | struct ipmi_device_id *device_id, |
214 | struct device *dev, | 213 | struct device *dev, |
215 | const char *sysfs_name, | ||
216 | unsigned char slave_addr); | 214 | unsigned char slave_addr); |
217 | 215 | ||
218 | /* | 216 | /* |