#define pr_fmt(fmt) …
#define dev_fmt(fmt) …
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/panic_notifier.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
#include <linux/notifier.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/rcupdate.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/workqueue.h>
#include <linux/uuid.h>
#include <linux/nospec.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#define IPMI_DRIVER_VERSION …
static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
static int ipmi_init_msghandler(void);
static void smi_recv_work(struct work_struct *t);
static void handle_new_recv_msgs(struct ipmi_smi *intf);
static void need_waiter(struct ipmi_smi *intf);
static int handle_one_recv_msg(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg);
static bool initialized;
static bool drvregistered;
enum ipmi_panic_event_op { … };
static const char *const ipmi_panic_event_str[] = …;
#ifdef CONFIG_IPMI_PANIC_STRING
#define IPMI_PANIC_DEFAULT …
#elif defined(CONFIG_IPMI_PANIC_EVENT)
#define IPMI_PANIC_DEFAULT …
#else
#define IPMI_PANIC_DEFAULT …
#endif
static enum ipmi_panic_event_op ipmi_send_panic_event = …;
static int panic_op_write_handler(const char *val,
const struct kernel_param *kp)
{ … }
static int panic_op_read_handler(char *buffer, const struct kernel_param *kp)
{ … }
static const struct kernel_param_ops panic_op_ops = …;
module_param_cb(…);
MODULE_PARM_DESC(…) …;
#define MAX_EVENTS_IN_QUEUE …
static unsigned long maintenance_mode_timeout_ms = …;
module_param(maintenance_mode_timeout_ms, ulong, 0644);
MODULE_PARM_DESC(…) …;
#define MAX_MSG_TIMEOUT …
static unsigned long default_retry_ms = …;
module_param(default_retry_ms, ulong, 0644);
MODULE_PARM_DESC(…) …;
static unsigned long default_maintenance_retry_ms = …;
module_param(default_maintenance_retry_ms, ulong, 0644);
MODULE_PARM_DESC(…) …;
static unsigned int default_max_retries = …;
module_param(default_max_retries, uint, 0644);
MODULE_PARM_DESC(…) …;
static unsigned int max_users = …;
module_param(max_users, uint, 0644);
MODULE_PARM_DESC(…) …;
static unsigned int max_msgs_per_user = …;
module_param(max_msgs_per_user, uint, 0644);
MODULE_PARM_DESC(…) …;
#define IPMI_TIMEOUT_TIME …
#define IPMI_TIMEOUT_JIFFIES …
#define IPMI_REQUEST_EV_TIME …
#define IPMI_DYN_DEV_ID_EXPIRY …
struct ipmi_user { … };
static struct workqueue_struct *remove_work_wq;
static struct ipmi_user *acquire_ipmi_user(struct ipmi_user *user, int *index)
__acquires(user->release_barrier)
{ … }
static void release_ipmi_user(struct ipmi_user *user, int index)
{ … }
struct cmd_rcvr { … };
struct seq_table { … };
#define STORE_SEQ_IN_MSGID(seq, seqid) …
#define GET_SEQ_FROM_MSGID(msgid, seq, seqid) …
#define NEXT_SEQID(seqid) …
#define IPMI_MAX_CHANNELS …
struct ipmi_channel { … };
struct ipmi_channel_set { … };
struct ipmi_my_addrinfo { … };
struct bmc_device { … };
#define to_bmc_device(x) …
static int bmc_get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc,
struct ipmi_device_id *id,
bool *guid_set, guid_t *guid);
enum ipmi_stat_indexes { … };
#define IPMI_IPMB_NUM_SEQ …
struct ipmi_smi { … };
#define to_si_intf_from_dev(device) …
static void __get_guid(struct ipmi_smi *intf);
static void __ipmi_bmc_unregister(struct ipmi_smi *intf);
static int __ipmi_bmc_register(struct ipmi_smi *intf,
struct ipmi_device_id *id,
bool guid_set, guid_t *guid, int intf_num);
static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id);
static struct platform_driver ipmidriver = …;
static DEFINE_MUTEX(ipmidriver_mutex);
static LIST_HEAD(ipmi_interfaces);
static DEFINE_MUTEX(ipmi_interfaces_mutex);
#define ipmi_interfaces_mutex_held() …
static struct srcu_struct ipmi_interfaces_srcu;
static LIST_HEAD(smi_watchers);
static DEFINE_MUTEX(smi_watchers_mutex);
#define ipmi_inc_stat(intf, stat) …
#define ipmi_get_stat(intf, stat) …
static const char * const addr_src_to_str[] = …;
const char *ipmi_addr_src_to_str(enum ipmi_addr_src src)
{ … }
EXPORT_SYMBOL(…);
static int is_lan_addr(struct ipmi_addr *addr)
{ … }
static int is_ipmb_addr(struct ipmi_addr *addr)
{ … }
static int is_ipmb_bcast_addr(struct ipmi_addr *addr)
{ … }
static int is_ipmb_direct_addr(struct ipmi_addr *addr)
{ … }
static void free_recv_msg_list(struct list_head *q)
{ … }
static void free_smi_msg_list(struct list_head *q)
{ … }
static void clean_up_interface_data(struct ipmi_smi *intf)
{ … }
static void intf_free(struct kref *ref)
{ … }
int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
{ … }
EXPORT_SYMBOL(…);
int ipmi_smi_watcher_unregister(struct ipmi_smi_watcher *watcher)
{ … }
EXPORT_SYMBOL(…);
static void
call_smi_watchers(int i, struct device *dev)
{ … }
static int
ipmi_addr_equal(struct ipmi_addr *addr1, struct ipmi_addr *addr2)
{ … }
int ipmi_validate_addr(struct ipmi_addr *addr, int len)
{ … }
EXPORT_SYMBOL(…);
unsigned int ipmi_addr_length(int addr_type)
{ … }
EXPORT_SYMBOL(…);
static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
{ … }
static void deliver_local_response(struct ipmi_smi *intf,
struct ipmi_recv_msg *msg)
{ … }
static void deliver_err_response(struct ipmi_smi *intf,
struct ipmi_recv_msg *msg, int err)
{ … }
static void smi_add_watch(struct ipmi_smi *intf, unsigned int flags)
{ … }
static void smi_remove_watch(struct ipmi_smi *intf, unsigned int flags)
{ … }
static int intf_next_seq(struct ipmi_smi *intf,
struct ipmi_recv_msg *recv_msg,
unsigned long timeout,
int retries,
int broadcast,
unsigned char *seq,
long *seqid)
{ … }
static int intf_find_seq(struct ipmi_smi *intf,
unsigned char seq,
short channel,
unsigned char cmd,
unsigned char netfn,
struct ipmi_addr *addr,
struct ipmi_recv_msg **recv_msg)
{ … }
static int intf_start_seq_timer(struct ipmi_smi *intf,
long msgid)
{ … }
static int intf_err_seq(struct ipmi_smi *intf,
long msgid,
unsigned int err)
{ … }
static void free_user_work(struct work_struct *work)
{ … }
int ipmi_create_user(unsigned int if_num,
const struct ipmi_user_hndl *handler,
void *handler_data,
struct ipmi_user **user)
{ … }
EXPORT_SYMBOL(…);
int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data)
{ … }
EXPORT_SYMBOL(…);
static void free_user(struct kref *ref)
{ … }
static void _ipmi_destroy_user(struct ipmi_user *user)
{ … }
int ipmi_destroy_user(struct ipmi_user *user)
{ … }
EXPORT_SYMBOL(…);
int ipmi_get_version(struct ipmi_user *user,
unsigned char *major,
unsigned char *minor)
{ … }
EXPORT_SYMBOL(…);
int ipmi_set_my_address(struct ipmi_user *user,
unsigned int channel,
unsigned char address)
{ … }
EXPORT_SYMBOL(…);
int ipmi_get_my_address(struct ipmi_user *user,
unsigned int channel,
unsigned char *address)
{ … }
EXPORT_SYMBOL(…);
int ipmi_set_my_LUN(struct ipmi_user *user,
unsigned int channel,
unsigned char LUN)
{ … }
EXPORT_SYMBOL(…);
int ipmi_get_my_LUN(struct ipmi_user *user,
unsigned int channel,
unsigned char *address)
{ … }
EXPORT_SYMBOL(…);
int ipmi_get_maintenance_mode(struct ipmi_user *user)
{ … }
EXPORT_SYMBOL(…);
static void maintenance_mode_update(struct ipmi_smi *intf)
{ … }
int ipmi_set_maintenance_mode(struct ipmi_user *user, int mode)
{ … }
EXPORT_SYMBOL(…);
int ipmi_set_gets_events(struct ipmi_user *user, bool val)
{ … }
EXPORT_SYMBOL(…);
static struct cmd_rcvr *find_cmd_rcvr(struct ipmi_smi *intf,
unsigned char netfn,
unsigned char cmd,
unsigned char chan)
{ … }
static int is_cmd_rcvr_exclusive(struct ipmi_smi *intf,
unsigned char netfn,
unsigned char cmd,
unsigned int chans)
{ … }
int ipmi_register_for_cmd(struct ipmi_user *user,
unsigned char netfn,
unsigned char cmd,
unsigned int chans)
{ … }
EXPORT_SYMBOL(…);
int ipmi_unregister_for_cmd(struct ipmi_user *user,
unsigned char netfn,
unsigned char cmd,
unsigned int chans)
{ … }
EXPORT_SYMBOL(…);
unsigned char
ipmb_checksum(unsigned char *data, int size)
{ … }
EXPORT_SYMBOL(…);
static inline void format_ipmb_msg(struct ipmi_smi_msg *smi_msg,
struct kernel_ipmi_msg *msg,
struct ipmi_ipmb_addr *ipmb_addr,
long msgid,
unsigned char ipmb_seq,
int broadcast,
unsigned char source_address,
unsigned char source_lun)
{ … }
static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg,
struct kernel_ipmi_msg *msg,
struct ipmi_lan_addr *lan_addr,
long msgid,
unsigned char ipmb_seq,
unsigned char source_lun)
{ … }
static struct ipmi_smi_msg *smi_add_send_msg(struct ipmi_smi *intf,
struct ipmi_smi_msg *smi_msg,
int priority)
{ … }
static void smi_send(struct ipmi_smi *intf,
const struct ipmi_smi_handlers *handlers,
struct ipmi_smi_msg *smi_msg, int priority)
{ … }
static bool is_maintenance_mode_cmd(struct kernel_ipmi_msg *msg)
{ … }
static int i_ipmi_req_sysintf(struct ipmi_smi *intf,
struct ipmi_addr *addr,
long msgid,
struct kernel_ipmi_msg *msg,
struct ipmi_smi_msg *smi_msg,
struct ipmi_recv_msg *recv_msg,
int retries,
unsigned int retry_time_ms)
{ … }
static int i_ipmi_req_ipmb(struct ipmi_smi *intf,
struct ipmi_addr *addr,
long msgid,
struct kernel_ipmi_msg *msg,
struct ipmi_smi_msg *smi_msg,
struct ipmi_recv_msg *recv_msg,
unsigned char source_address,
unsigned char source_lun,
int retries,
unsigned int retry_time_ms)
{ … }
static int i_ipmi_req_ipmb_direct(struct ipmi_smi *intf,
struct ipmi_addr *addr,
long msgid,
struct kernel_ipmi_msg *msg,
struct ipmi_smi_msg *smi_msg,
struct ipmi_recv_msg *recv_msg,
unsigned char source_lun)
{ … }
static int i_ipmi_req_lan(struct ipmi_smi *intf,
struct ipmi_addr *addr,
long msgid,
struct kernel_ipmi_msg *msg,
struct ipmi_smi_msg *smi_msg,
struct ipmi_recv_msg *recv_msg,
unsigned char source_lun,
int retries,
unsigned int retry_time_ms)
{ … }
static int i_ipmi_request(struct ipmi_user *user,
struct ipmi_smi *intf,
struct ipmi_addr *addr,
long msgid,
struct kernel_ipmi_msg *msg,
void *user_msg_data,
void *supplied_smi,
struct ipmi_recv_msg *supplied_recv,
int priority,
unsigned char source_address,
unsigned char source_lun,
int retries,
unsigned int retry_time_ms)
{ … }
static int check_addr(struct ipmi_smi *intf,
struct ipmi_addr *addr,
unsigned char *saddr,
unsigned char *lun)
{ … }
int ipmi_request_settime(struct ipmi_user *user,
struct ipmi_addr *addr,
long msgid,
struct kernel_ipmi_msg *msg,
void *user_msg_data,
int priority,
int retries,
unsigned int retry_time_ms)
{ … }
EXPORT_SYMBOL(…);
int ipmi_request_supply_msgs(struct ipmi_user *user,
struct ipmi_addr *addr,
long msgid,
struct kernel_ipmi_msg *msg,
void *user_msg_data,
void *supplied_smi,
struct ipmi_recv_msg *supplied_recv,
int priority)
{ … }
EXPORT_SYMBOL(…);
static void bmc_device_id_handler(struct ipmi_smi *intf,
struct ipmi_recv_msg *msg)
{ … }
static int
send_get_device_id_cmd(struct ipmi_smi *intf)
{ … }
static int __get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc)
{ … }
static int __bmc_get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc,
struct ipmi_device_id *id,
bool *guid_set, guid_t *guid, int intf_num)
{ … }
static int bmc_get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc,
struct ipmi_device_id *id,
bool *guid_set, guid_t *guid)
{ … }
static ssize_t device_id_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(device_id);
static ssize_t provides_device_sdrs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(provides_device_sdrs);
static ssize_t revision_show(struct device *dev, struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(revision);
static ssize_t firmware_revision_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(firmware_revision);
static ssize_t ipmi_version_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(ipmi_version);
static ssize_t add_dev_support_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR(additional_device_support, S_IRUGO, add_dev_support_show,
NULL);
static ssize_t manufacturer_id_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(manufacturer_id);
static ssize_t product_id_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(product_id);
static ssize_t aux_firmware_rev_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR(aux_firmware_revision, S_IRUGO, aux_firmware_rev_show, NULL);
static ssize_t guid_show(struct device *dev, struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(guid);
static struct attribute *bmc_dev_attrs[] = …;
static umode_t bmc_dev_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int idx)
{ … }
static const struct attribute_group bmc_dev_attr_group = …;
static const struct attribute_group *bmc_dev_attr_groups[] = …;
static const struct device_type bmc_device_type = …;
static int __find_bmc_guid(struct device *dev, const void *data)
{ … }
static struct bmc_device *ipmi_find_bmc_guid(struct device_driver *drv,
guid_t *guid)
{ … }
struct prod_dev_id { … };
static int __find_bmc_prod_dev_id(struct device *dev, const void *data)
{ … }
static struct bmc_device *ipmi_find_bmc_prod_dev_id(
struct device_driver *drv,
unsigned int product_id, unsigned char device_id)
{ … }
static DEFINE_IDA(ipmi_bmc_ida);
static void
release_bmc_device(struct device *dev)
{ … }
static void cleanup_bmc_work(struct work_struct *work)
{ … }
static void
cleanup_bmc_device(struct kref *ref)
{ … }
static void __ipmi_bmc_unregister(struct ipmi_smi *intf)
{ … }
static void ipmi_bmc_unregister(struct ipmi_smi *intf)
{ … }
static int __ipmi_bmc_register(struct ipmi_smi *intf,
struct ipmi_device_id *id,
bool guid_set, guid_t *guid, int intf_num)
{ … }
static int
send_guid_cmd(struct ipmi_smi *intf, int chan)
{ … }
static void guid_handler(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
{ … }
static void __get_guid(struct ipmi_smi *intf)
{ … }
static int
send_channel_info_cmd(struct ipmi_smi *intf, int chan)
{ … }
static void
channel_handler(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
{ … }
static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id)
{ … }
static void ipmi_poll(struct ipmi_smi *intf)
{ … }
void ipmi_poll_interface(struct ipmi_user *user)
{ … }
EXPORT_SYMBOL(…);
static ssize_t nr_users_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(nr_users);
static ssize_t nr_msgs_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{ … }
static DEVICE_ATTR_RO(nr_msgs);
static void redo_bmc_reg(struct work_struct *work)
{ … }
int ipmi_add_smi(struct module *owner,
const struct ipmi_smi_handlers *handlers,
void *send_info,
struct device *si_dev,
unsigned char slave_addr)
{ … }
EXPORT_SYMBOL(…);
static void deliver_smi_err_response(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg,
unsigned char err)
{ … }
static void cleanup_smi_msgs(struct ipmi_smi *intf)
{ … }
void ipmi_unregister_smi(struct ipmi_smi *intf)
{ … }
EXPORT_SYMBOL(…);
static int handle_ipmb_get_msg_rsp(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static int handle_ipmb_get_msg_cmd(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static int handle_ipmb_direct_rcv_cmd(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static int handle_ipmb_direct_rcv_rsp(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static int handle_lan_get_msg_rsp(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static int handle_lan_get_msg_cmd(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static int handle_oem_get_msg_cmd(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg,
struct ipmi_smi_msg *msg)
{ … }
static int handle_read_event_rsp(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static int handle_bmc_rsp(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static int handle_one_recv_msg(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
static void handle_new_recv_msgs(struct ipmi_smi *intf)
{ … }
static void smi_recv_work(struct work_struct *t)
{ … }
void ipmi_smi_msg_received(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg)
{ … }
EXPORT_SYMBOL(…);
void ipmi_smi_watchdog_pretimeout(struct ipmi_smi *intf)
{ … }
EXPORT_SYMBOL(…);
static struct ipmi_smi_msg *
smi_from_recv_msg(struct ipmi_smi *intf, struct ipmi_recv_msg *recv_msg,
unsigned char seq, long seqid)
{ … }
static void check_msg_timeout(struct ipmi_smi *intf, struct seq_table *ent,
struct list_head *timeouts,
unsigned long timeout_period,
int slot, unsigned long *flags,
bool *need_timer)
{ … }
static bool ipmi_timeout_handler(struct ipmi_smi *intf,
unsigned long timeout_period)
{ … }
static void ipmi_request_event(struct ipmi_smi *intf)
{ … }
static struct timer_list ipmi_timer;
static atomic_t stop_operation;
static void ipmi_timeout(struct timer_list *unused)
{ … }
static void need_waiter(struct ipmi_smi *intf)
{ … }
static atomic_t smi_msg_inuse_count = …;
static atomic_t recv_msg_inuse_count = …;
static void free_smi_msg(struct ipmi_smi_msg *msg)
{ … }
struct ipmi_smi_msg *ipmi_alloc_smi_msg(void)
{ … }
EXPORT_SYMBOL(…);
static void free_recv_msg(struct ipmi_recv_msg *msg)
{ … }
static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void)
{ … }
void ipmi_free_recv_msg(struct ipmi_recv_msg *msg)
{ … }
EXPORT_SYMBOL(…);
static atomic_t panic_done_count = …;
static void dummy_smi_done_handler(struct ipmi_smi_msg *msg)
{ … }
static void dummy_recv_done_handler(struct ipmi_recv_msg *msg)
{ … }
static void ipmi_panic_request_and_wait(struct ipmi_smi *intf,
struct ipmi_addr *addr,
struct kernel_ipmi_msg *msg)
{ … }
static void event_receiver_fetcher(struct ipmi_smi *intf,
struct ipmi_recv_msg *msg)
{ … }
static void device_id_fetcher(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
{ … }
static void send_panic_events(struct ipmi_smi *intf, char *str)
{ … }
static int has_panicked;
static int panic_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{ … }
static int ipmi_register_driver(void)
{ … }
static struct notifier_block panic_block = …;
static int ipmi_init_msghandler(void)
{ … }
static int __init ipmi_init_msghandler_mod(void)
{ … }
static void __exit cleanup_ipmi(void)
{ … }
module_exit(cleanup_ipmi);
module_init(…) …;
MODULE_LICENSE(…) …;
MODULE_AUTHOR(…) …;
MODULE_DESCRIPTION(…) …;
MODULE_VERSION(…);
MODULE_SOFTDEP(…) …;