linux/drivers/char/ipmi/ipmi_poweroff.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * ipmi_poweroff.c
 *
 * MontaVista IPMI Poweroff extension to sys_reboot
 *
 * Author: MontaVista Software, Inc.
 *         Steven Dake <[email protected]>
 *         Corey Minyard <[email protected]>
 *         [email protected]
 *
 * Copyright 2002,2004 MontaVista Software Inc.
 */

#define pr_fmt(fmt)

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/completion.h>
#include <linux/pm.h>
#include <linux/kdev_t.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>

static void ipmi_po_smi_gone(int if_num);
static void ipmi_po_new_smi(int if_num, struct device *device);

/* Definitions for controlling power off (if the system supports it).  It
 * conveniently matches the IPMI chassis control values. */
#define IPMI_CHASSIS_POWER_DOWN
#define IPMI_CHASSIS_POWER_CYCLE

/* the IPMI data command */
static int poweroff_powercycle;

/* Which interface to use, -1 means the first we see. */
static int ifnum_to_use =;

/* Our local state. */
static int ready;
static struct ipmi_user *ipmi_user;
static int ipmi_ifnum;
static void (*specific_poweroff_func)(struct ipmi_user *user);

/* Holds the old poweroff function so we can restore it on removal. */
static void (*old_poweroff_func)(void);

static int set_param_ifnum(const char *val, const struct kernel_param *kp)
{}

module_param_call();
MODULE_PARM_DESC();

/* parameter definition to allow user to flag power cycle */
module_param(poweroff_powercycle, int, 0644);
MODULE_PARM_DESC();

/* Stuff from the get device id command. */
static unsigned int mfg_id;
static unsigned int prod_id;
static unsigned char capabilities;
static unsigned char ipmi_version;

/*
 * We use our own messages for this operation, we don't let the system
 * allocate them, since we may be in a panic situation.  The whole
 * thing is single-threaded, anyway, so multiple messages are not
 * required.
 */
static atomic_t dummy_count =;
static void dummy_smi_free(struct ipmi_smi_msg *msg)
{}
static void dummy_recv_free(struct ipmi_recv_msg *msg)
{}
static struct ipmi_smi_msg halt_smi_msg =;
static struct ipmi_recv_msg halt_recv_msg =;


/*
 * Code to send a message and wait for the response.
 */

static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
{}

static const struct ipmi_user_hndl ipmi_poweroff_handler =;


static int ipmi_request_wait_for_response(struct ipmi_user       *user,
					  struct ipmi_addr       *addr,
					  struct kernel_ipmi_msg *send_msg)
{}

/* Wait for message to complete, spinning. */
static int ipmi_request_in_rc_mode(struct ipmi_user       *user,
				   struct ipmi_addr       *addr,
				   struct kernel_ipmi_msg *send_msg)
{}

/*
 * ATCA Support
 */

#define IPMI_NETFN_ATCA
#define IPMI_ATCA_SET_POWER_CMD
#define IPMI_ATCA_GET_ADDR_INFO_CMD
#define IPMI_PICMG_ID

#define IPMI_NETFN_OEM
#define IPMI_ATCA_PPS_GRACEFUL_RESTART
#define IPMI_ATCA_PPS_IANA
#define IPMI_MOTOROLA_MANUFACTURER_ID
#define IPMI_MOTOROLA_PPS_IPMC_PRODUCT_ID

static void (*atca_oem_poweroff_hook)(struct ipmi_user *user);

static void pps_poweroff_atca(struct ipmi_user *user)
{}

static int ipmi_atca_detect(struct ipmi_user *user)
{}

static void ipmi_poweroff_atca(struct ipmi_user *user)
{}

/*
 * CPI1 Support
 */

#define IPMI_NETFN_OEM_1
#define OEM_GRP_CMD_SET_RESET_STATE
#define OEM_GRP_CMD_SET_POWER_STATE
#define IPMI_NETFN_OEM_8
#define OEM_GRP_CMD_REQUEST_HOTSWAP_CTRL
#define OEM_GRP_CMD_GET_SLOT_GA
#define IPMI_NETFN_SENSOR_EVT
#define IPMI_CMD_GET_EVENT_RECEIVER

#define IPMI_CPI1_PRODUCT_ID
#define IPMI_CPI1_MANUFACTURER_ID

static int ipmi_cpi1_detect(struct ipmi_user *user)
{}

static void ipmi_poweroff_cpi1(struct ipmi_user *user)
{}

/*
 * ipmi_dell_chassis_detect()
 * Dell systems with IPMI < 1.5 don't set the chassis capability bit
 * but they can handle a chassis poweroff or powercycle command.
 */

#define DELL_IANA_MFR_ID
static int ipmi_dell_chassis_detect(struct ipmi_user *user)
{}

/*
 * ipmi_hp_chassis_detect()
 * HP PA-RISC servers rp3410/rp3440, the C8000 workstation and the rx2600 and
 * zx6000 machines support IPMI vers 1 and don't set the chassis capability bit
 * but they can handle a chassis poweroff or powercycle command.
 */

#define HP_IANA_MFR_ID
#define HP_BMC_PROD_ID
static int ipmi_hp_chassis_detect(struct ipmi_user *user)
{}

/*
 * Standard chassis support
 */

#define IPMI_NETFN_CHASSIS_REQUEST
#define IPMI_CHASSIS_CONTROL_CMD

static int ipmi_chassis_detect(struct ipmi_user *user)
{}

static void ipmi_poweroff_chassis(struct ipmi_user *user)
{}


/* Table of possible power off functions. */
struct poweroff_function {};

static struct poweroff_function poweroff_functions[] =;
#define NUM_PO_FUNCS


/* Called on a powerdown request. */
static void ipmi_poweroff_function(void)
{}

/* Wait for an IPMI interface to be installed, the first one installed
   will be grabbed by this code and used to perform the powerdown. */
static void ipmi_po_new_smi(int if_num, struct device *device)
{}

static void ipmi_po_smi_gone(int if_num)
{}

static struct ipmi_smi_watcher smi_watcher =;


#ifdef CONFIG_PROC_FS
#include <linux/sysctl.h>

static struct ctl_table ipmi_table[] =;

static struct ctl_table_header *ipmi_table_header;
#endif /* CONFIG_PROC_FS */

/*
 * Startup and shutdown functions.
 */
static int __init ipmi_poweroff_init(void)
{}

#ifdef MODULE
static void __exit ipmi_poweroff_cleanup(void)
{
	int rv;

#ifdef CONFIG_PROC_FS
	unregister_sysctl_table(ipmi_table_header);
#endif

	ipmi_smi_watcher_unregister(&smi_watcher);

	if (ready) {
		rv = ipmi_destroy_user(ipmi_user);
		if (rv)
			pr_err("could not cleanup the IPMI user: 0x%x\n", rv);
		pm_power_off = old_poweroff_func;
	}
}
module_exit(ipmi_poweroff_cleanup);
#endif

module_init();
MODULE_LICENSE();
MODULE_AUTHOR();
MODULE_DESCRIPTION();