brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · a5ced88 Raw
210 lines · c
1/* SPDX-License-Identifier: GPL-2.0-or-later */2 3/*4 * IBM ASM Service Processor Device Driver5 *6 * Copyright (C) IBM Corporation, 20047 *8 * Author: Max Asböck <amax@us.ibm.com>9 */10 11#include <linux/kernel.h>12#include <linux/types.h>13#include <linux/errno.h>14#include <linux/list.h>15#include <linux/wait.h>16#include <linux/spinlock.h>17#include <linux/slab.h>18#include <linux/module.h>19#include <linux/interrupt.h>20#include <linux/kref.h>21#include <linux/device.h>22#include <linux/input.h>23#include <linux/time64.h>24 25/* Driver identification */26#define DRIVER_NAME	"ibmasm"27#define DRIVER_VERSION  "1.0"28#define DRIVER_AUTHOR   "Max Asbock <masbock@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"29#define DRIVER_DESC     "IBM ASM Service Processor Driver"30 31#define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME)32#define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME)33 34extern int ibmasm_debug;35#define dbg(STR, ARGS...)					\36	do {							\37		if (ibmasm_debug)				\38			printk(KERN_DEBUG STR , ##ARGS);	\39	} while (0)40 41static inline char *get_timestamp(char *buf)42{43	struct timespec64 now;44 45	ktime_get_real_ts64(&now);46	sprintf(buf, "%llu.%.08lu", (long long)now.tv_sec,47				now.tv_nsec / NSEC_PER_USEC);48	return buf;49}50 51#define IBMASM_CMD_PENDING	052#define IBMASM_CMD_COMPLETE	153#define IBMASM_CMD_FAILED	254 55#define IBMASM_CMD_TIMEOUT_NORMAL	4556#define IBMASM_CMD_TIMEOUT_EXTRA	24057 58#define IBMASM_CMD_MAX_BUFFER_SIZE	0x800059 60#define REVERSE_HEARTBEAT_TIMEOUT	12061 62#define HEARTBEAT_BUFFER_SIZE		0x40063 64#ifdef IA6465#define IBMASM_DRIVER_VPD "Lin64 6.08      "66#else67#define IBMASM_DRIVER_VPD "Lin32 6.08      "68#endif69 70#define SYSTEM_STATE_OS_UP      571#define SYSTEM_STATE_OS_DOWN    472 73#define IBMASM_NAME_SIZE	1674 75#define IBMASM_NUM_EVENTS	1076#define IBMASM_EVENT_MAX_SIZE	2048u77 78 79struct command {80	struct list_head	queue_node;81	wait_queue_head_t	wait;82	unsigned char		*buffer;83	size_t			buffer_size;84	int			status;85	struct kref		kref;86	spinlock_t		*lock;87};88#define to_command(c) container_of(c, struct command, kref)89 90void ibmasm_free_command(struct kref *kref);91static inline void command_put(struct command *cmd)92{93	unsigned long flags;94	spinlock_t *lock = cmd->lock;95 96	spin_lock_irqsave(lock, flags);97	kref_put(&cmd->kref, ibmasm_free_command);98	spin_unlock_irqrestore(lock, flags);99}100 101static inline void command_get(struct command *cmd)102{103	kref_get(&cmd->kref);104}105 106 107struct ibmasm_event {108	unsigned int	serial_number;109	unsigned int	data_size;110	unsigned char	data[IBMASM_EVENT_MAX_SIZE];111};112 113struct event_buffer {114	struct ibmasm_event	events[IBMASM_NUM_EVENTS];115	unsigned int		next_serial_number;116	unsigned int		next_index;117	struct list_head	readers;118};119 120struct event_reader {121	int			cancelled;122	unsigned int		next_serial_number;123	wait_queue_head_t	wait;124	struct list_head	node;125	unsigned int		data_size;126	unsigned char		data[IBMASM_EVENT_MAX_SIZE];127};128 129struct reverse_heartbeat {130	wait_queue_head_t	wait;131	unsigned int		stopped;132};133 134struct ibmasm_remote {135	struct input_dev *keybd_dev;136	struct input_dev *mouse_dev;137};138 139struct service_processor {140	struct list_head	node;141	spinlock_t		lock;142	void __iomem		*base_address;143	unsigned int		irq;144	struct command		*current_command;145	struct command		*heartbeat;146	struct list_head	command_queue;147	struct event_buffer	*event_buffer;148	char			dirname[IBMASM_NAME_SIZE];149	char			devname[IBMASM_NAME_SIZE];150	unsigned int		number;151	struct ibmasm_remote	remote;152	int			serial_line;153	struct device		*dev;154};155 156/* command processing */157struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);158void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);159void ibmasm_wait_for_response(struct command *cmd, int timeout);160void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);161 162/* event processing */163int ibmasm_event_buffer_init(struct service_processor *sp);164void ibmasm_event_buffer_exit(struct service_processor *sp);165void ibmasm_receive_event(struct service_processor *sp, void *data,  unsigned int data_size);166void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);167void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);168int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);169void ibmasm_cancel_next_event(struct event_reader *reader);170 171/* heartbeat - from SP to OS */172void ibmasm_register_panic_notifier(void);173void ibmasm_unregister_panic_notifier(void);174int ibmasm_heartbeat_init(struct service_processor *sp);175void ibmasm_heartbeat_exit(struct service_processor *sp);176void ibmasm_receive_heartbeat(struct service_processor *sp,  void *message, size_t size);177 178/* reverse heartbeat - from OS to SP */179void ibmasm_init_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);180int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_heartbeat *rhb);181void ibmasm_stop_reverse_heartbeat(struct reverse_heartbeat *rhb);182 183/* dot commands */184void ibmasm_receive_message(struct service_processor *sp, void *data, int data_size);185int ibmasm_send_driver_vpd(struct service_processor *sp);186int ibmasm_send_os_state(struct service_processor *sp, int os_state);187 188/* low level message processing */189int ibmasm_send_i2o_message(struct service_processor *sp);190irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id);191 192/* remote console */193void ibmasm_handle_mouse_interrupt(struct service_processor *sp);194int ibmasm_init_remote_input_dev(struct service_processor *sp);195void ibmasm_free_remote_input_dev(struct service_processor *sp);196 197/* file system */198int ibmasmfs_register(void);199void ibmasmfs_unregister(void);200void ibmasmfs_add_sp(struct service_processor *sp);201 202/* uart */203#if IS_ENABLED(CONFIG_SERIAL_8250)204void ibmasm_register_uart(struct service_processor *sp);205void ibmasm_unregister_uart(struct service_processor *sp);206#else207#define ibmasm_register_uart(sp)	do { } while(0)208#define ibmasm_unregister_uart(sp)	do { } while(0)209#endif210