diff options
Diffstat (limited to 'include/linux/ipmi_smi.h')
| -rw-r--r-- | include/linux/ipmi_smi.h | 115 |
1 files changed, 100 insertions, 15 deletions
diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 8c4e2ab696c3..892e2d656e1e 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -31,6 +31,67 @@ struct device; struct ipmi_smi; /* + * Flags for set_check_watch() below. Tells if the SMI should be + * waiting for watchdog timeouts, commands and/or messages. + */ +#define IPMI_WATCH_MASK_CHECK_MESSAGES (1 << 0) +#define IPMI_WATCH_MASK_CHECK_WATCHDOG (1 << 1) +#define IPMI_WATCH_MASK_CHECK_COMMANDS (1 << 2) + +/* + * SMI messages + * + * When communicating with an SMI, messages come in two formats: + * + * * Normal (to a BMC over a BMC interface) + * + * * IPMB (over a IPMB to another MC) + * + * When normal, commands are sent using the format defined by a + * standard message over KCS (NetFn must be even): + * + * +-----------+-----+------+ + * | NetFn/LUN | Cmd | Data | + * +-----------+-----+------+ + * + * And responses, similarly, with an completion code added (NetFn must + * be odd): + * + * +-----------+-----+------+------+ + * | NetFn/LUN | Cmd | CC | Data | + * +-----------+-----+------+------+ + * + * With normal messages, only commands are sent and only responses are + * received. + * + * In IPMB mode, we are acting as an IPMB device. Commands will be in + * the following format (NetFn must be even): + * + * +-------------+------+-------------+-----+------+ + * | NetFn/rsLUN | Addr | rqSeq/rqLUN | Cmd | Data | + * +-------------+------+-------------+-----+------+ + * + * Responses will using the following format: + * + * +-------------+------+-------------+-----+------+------+ + * | NetFn/rqLUN | Addr | rqSeq/rsLUN | Cmd | CC | Data | + * +-------------+------+-------------+-----+------+------+ + * + * This is similar to the format defined in the IPMB manual section + * 2.11.1 with the checksums and the first address removed. Also, the + * address is always the remote address. + * + * IPMB messages can be commands and responses in both directions. + * Received commands are handled as received commands from the message + * queue. + */ + +enum ipmi_smi_msg_type { + IPMI_SMI_MSG_TYPE_NORMAL = 0, + IPMI_SMI_MSG_TYPE_IPMB_DIRECT +}; + +/* * Messages to/from the lower layer. The smi interface will take one * of these to send. After the send has occurred and a response has * been received, it will report this same data structure back up to @@ -46,8 +107,11 @@ struct ipmi_smi; struct ipmi_smi_msg { struct list_head link; - long msgid; - void *user_data; + enum ipmi_smi_msg_type type; + + long msgid; + /* Response to this message, will be NULL if not from a user request. */ + struct ipmi_recv_msg *recv_msg; int data_size; unsigned char data[IPMI_MAX_MSG_LENGTH]; @@ -55,14 +119,26 @@ struct ipmi_smi_msg { int rsp_size; unsigned char rsp[IPMI_MAX_MSG_LENGTH]; - /* Will be called when the system is done with the message - (presumably to free it). */ + /* + * Will be called when the system is done with the message + * (presumably to free it). + */ void (*done)(struct ipmi_smi_msg *msg); }; +#define INIT_IPMI_SMI_MSG(done_handler) \ +{ \ + .done = done_handler, \ + .type = IPMI_SMI_MSG_TYPE_NORMAL \ +} + struct ipmi_smi_handlers { struct module *owner; + /* Capabilities of the SMI. */ +#define IPMI_SMI_CAN_HANDLE_IPMB_DIRECT (1 << 0) + unsigned int flags; + /* * The low-level interface cannot start sending messages to * the upper layer until this function is called. This may @@ -93,9 +169,11 @@ struct ipmi_smi_handlers { * are held when this is run. Message are delivered one at * a time by the message handler, a new message will not be * delivered until the previous message is returned. + * + * This can return an error if the SMI is not in a state where it + * can send a message. */ - void (*sender)(void *send_info, - struct ipmi_smi_msg *msg); + int (*sender)(void *send_info, struct ipmi_smi_msg *msg); /* * Called by the upper layer to request that we try to get @@ -105,12 +183,15 @@ struct ipmi_smi_handlers { /* * Called by the upper layer when some user requires that the - * interface watch for events, received messages, watchdog - * pretimeouts, or not. Used by the SMI to know if it should - * watch for these. This may be NULL if the SMI does not - * implement it. + * interface watch for received messages and watchdog + * pretimeouts (basically do a "Get Flags", or not. Used by + * the SMI to know if it should watch for these. This may be + * NULL if the SMI does not implement it. watch_mask is from + * IPMI_WATCH_MASK_xxx above. The interface should run slower + * timeouts for just watchdog checking or faster timeouts when + * waiting for the message queue. */ - void (*set_need_watch)(void *send_info, bool enable); + void (*set_need_watch)(void *send_info, unsigned int watch_mask); /* * Called when flushing all pending messages. @@ -211,10 +292,14 @@ static inline int ipmi_demangle_device_id(uint8_t netfn, uint8_t cmd, * is called, and the lower layer must get the interface from that * call. */ -int ipmi_register_smi(const struct ipmi_smi_handlers *handlers, - void *send_info, - struct device *dev, - unsigned char slave_addr); +int ipmi_add_smi(struct module *owner, + const struct ipmi_smi_handlers *handlers, + void *send_info, + struct device *dev, + unsigned char slave_addr); + +#define ipmi_register_smi(handlers, send_info, dev, slave_addr) \ + ipmi_add_smi(THIS_MODULE, handlers, send_info, dev, slave_addr) /* * Remove a low-level interface from the IPMI driver. This will |
