xref: /openbmc/linux/drivers/char/ipmi/ipmi_ssif.c (revision e87443a5)
1243ac210SCorey Minyard // SPDX-License-Identifier: GPL-2.0+
225930707SCorey Minyard /*
325930707SCorey Minyard  * ipmi_ssif.c
425930707SCorey Minyard  *
525930707SCorey Minyard  * The interface to the IPMI driver for SMBus access to a SMBus
625930707SCorey Minyard  * compliant device.  Called SSIF by the IPMI spec.
725930707SCorey Minyard  *
825930707SCorey Minyard  * Author: Intel Corporation
925930707SCorey Minyard  *         Todd Davis <todd.c.davis@intel.com>
1025930707SCorey Minyard  *
1125930707SCorey Minyard  * Rewritten by Corey Minyard <minyard@acm.org> to support the
1225930707SCorey Minyard  * non-blocking I2C interface, add support for multi-part
1325930707SCorey Minyard  * transactions, add PEC support, and general clenaup.
1425930707SCorey Minyard  *
1525930707SCorey Minyard  * Copyright 2003 Intel Corporation
1625930707SCorey Minyard  * Copyright 2005 MontaVista Software
1725930707SCorey Minyard  */
1825930707SCorey Minyard 
1925930707SCorey Minyard /*
2025930707SCorey Minyard  * This file holds the "policy" for the interface to the SSIF state
2125930707SCorey Minyard  * machine.  It does the configuration, handles timers and interrupts,
2225930707SCorey Minyard  * and drives the real SSIF state machine.
2325930707SCorey Minyard  */
2425930707SCorey Minyard 
2525880f7dSJoe Perches #define pr_fmt(fmt) "ipmi_ssif: " fmt
2683af4194SCorey Minyard #define dev_fmt(fmt) "ipmi_ssif: " fmt
2725880f7dSJoe Perches 
2825930707SCorey Minyard #if defined(MODVERSIONS)
2925930707SCorey Minyard #include <linux/modversions.h>
3025930707SCorey Minyard #endif
3125930707SCorey Minyard 
3225930707SCorey Minyard #include <linux/module.h>
3325930707SCorey Minyard #include <linux/moduleparam.h>
3425930707SCorey Minyard #include <linux/sched.h>
3525930707SCorey Minyard #include <linux/seq_file.h>
3625930707SCorey Minyard #include <linux/timer.h>
3725930707SCorey Minyard #include <linux/delay.h>
3825930707SCorey Minyard #include <linux/errno.h>
3925930707SCorey Minyard #include <linux/spinlock.h>
4025930707SCorey Minyard #include <linux/slab.h>
4125930707SCorey Minyard #include <linux/list.h>
4225930707SCorey Minyard #include <linux/i2c.h>
4325930707SCorey Minyard #include <linux/ipmi_smi.h>
4425930707SCorey Minyard #include <linux/init.h>
4525930707SCorey Minyard #include <linux/dmi.h>
4625930707SCorey Minyard #include <linux/kthread.h>
4725930707SCorey Minyard #include <linux/acpi.h>
48e3fe1427SCorey Minyard #include <linux/ctype.h>
49526290aaSAmitoj Kaur Chawla #include <linux/time64.h>
500944d889SCorey Minyard #include "ipmi_dmi.h"
5125930707SCorey Minyard 
5225930707SCorey Minyard #define DEVICE_NAME "ipmi_ssif"
5325930707SCorey Minyard 
5425930707SCorey Minyard #define IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD	0x57
5525930707SCorey Minyard 
5625930707SCorey Minyard #define	SSIF_IPMI_REQUEST			2
5725930707SCorey Minyard #define	SSIF_IPMI_MULTI_PART_REQUEST_START	6
5825930707SCorey Minyard #define	SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE	7
5910042504SCorey Minyard #define	SSIF_IPMI_MULTI_PART_REQUEST_END	8
6025930707SCorey Minyard #define	SSIF_IPMI_RESPONSE			3
6125930707SCorey Minyard #define	SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE	9
6225930707SCorey Minyard 
6325930707SCorey Minyard /* ssif_debug is a bit-field
6425930707SCorey Minyard  *	SSIF_DEBUG_MSG -	commands and their responses
6525930707SCorey Minyard  *	SSIF_DEBUG_STATES -	message states
6625930707SCorey Minyard  *	SSIF_DEBUG_TIMING -	 Measure times between events in the driver
6725930707SCorey Minyard  */
6825930707SCorey Minyard #define SSIF_DEBUG_TIMING	4
6925930707SCorey Minyard #define SSIF_DEBUG_STATE	2
7025930707SCorey Minyard #define SSIF_DEBUG_MSG		1
7125930707SCorey Minyard #define SSIF_NODEBUG		0
7225930707SCorey Minyard #define SSIF_DEFAULT_DEBUG	(SSIF_NODEBUG)
7325930707SCorey Minyard 
7425930707SCorey Minyard /*
7525930707SCorey Minyard  * Timer values
7625930707SCorey Minyard  */
7700bb7e76SCorey Minyard #define SSIF_MSG_USEC		60000	/* 60ms between message tries (T3). */
7800bb7e76SCorey Minyard #define SSIF_REQ_RETRY_USEC	60000	/* 60ms between send retries (T6). */
7925930707SCorey Minyard #define SSIF_MSG_PART_USEC	5000	/* 5ms for a message part */
8025930707SCorey Minyard 
8125930707SCorey Minyard /* How many times to we retry sending/receiving the message. */
8225930707SCorey Minyard #define	SSIF_SEND_RETRIES	5
8325930707SCorey Minyard #define	SSIF_RECV_RETRIES	250
8425930707SCorey Minyard 
8525930707SCorey Minyard #define SSIF_MSG_MSEC		(SSIF_MSG_USEC / 1000)
8600bb7e76SCorey Minyard #define SSIF_REQ_RETRY_MSEC	(SSIF_REQ_RETRY_USEC / 1000)
8725930707SCorey Minyard #define SSIF_MSG_JIFFIES	((SSIF_MSG_USEC * 1000) / TICK_NSEC)
8800bb7e76SCorey Minyard #define SSIF_REQ_RETRY_JIFFIES	((SSIF_REQ_RETRY_USEC * 1000) / TICK_NSEC)
8925930707SCorey Minyard #define SSIF_MSG_PART_JIFFIES	((SSIF_MSG_PART_USEC * 1000) / TICK_NSEC)
9025930707SCorey Minyard 
91a1466ec5SCorey Minyard /*
92a1466ec5SCorey Minyard  * Timeout for the watch, only used for get flag timer.
93a1466ec5SCorey Minyard  */
94c65ea996SCorey Minyard #define SSIF_WATCH_MSG_TIMEOUT		msecs_to_jiffies(10)
95c65ea996SCorey Minyard #define SSIF_WATCH_WATCHDOG_TIMEOUT	msecs_to_jiffies(250)
96a1466ec5SCorey Minyard 
9725930707SCorey Minyard enum ssif_intf_state {
988230831cSCorey Minyard 	SSIF_IDLE,
9925930707SCorey Minyard 	SSIF_GETTING_FLAGS,
10025930707SCorey Minyard 	SSIF_GETTING_EVENTS,
10125930707SCorey Minyard 	SSIF_CLEARING_FLAGS,
10225930707SCorey Minyard 	SSIF_GETTING_MESSAGES,
10325930707SCorey Minyard 	/* FIXME - add watchdog stuff. */
10425930707SCorey Minyard };
10525930707SCorey Minyard 
1068230831cSCorey Minyard #define IS_SSIF_IDLE(ssif) ((ssif)->ssif_state == SSIF_IDLE \
10725930707SCorey Minyard 			    && (ssif)->curr_msg == NULL)
10825930707SCorey Minyard 
10925930707SCorey Minyard /*
11025930707SCorey Minyard  * Indexes into stats[] in ssif_info below.
11125930707SCorey Minyard  */
11225930707SCorey Minyard enum ssif_stat_indexes {
11325930707SCorey Minyard 	/* Number of total messages sent. */
11425930707SCorey Minyard 	SSIF_STAT_sent_messages = 0,
11525930707SCorey Minyard 
11625930707SCorey Minyard 	/*
11725930707SCorey Minyard 	 * Number of message parts sent.  Messages may be broken into
11825930707SCorey Minyard 	 * parts if they are long.
11925930707SCorey Minyard 	 */
12025930707SCorey Minyard 	SSIF_STAT_sent_messages_parts,
12125930707SCorey Minyard 
12225930707SCorey Minyard 	/*
12325930707SCorey Minyard 	 * Number of time a message was retried.
12425930707SCorey Minyard 	 */
12525930707SCorey Minyard 	SSIF_STAT_send_retries,
12625930707SCorey Minyard 
12725930707SCorey Minyard 	/*
12825930707SCorey Minyard 	 * Number of times the send of a message failed.
12925930707SCorey Minyard 	 */
13025930707SCorey Minyard 	SSIF_STAT_send_errors,
13125930707SCorey Minyard 
13225930707SCorey Minyard 	/*
13325930707SCorey Minyard 	 * Number of message responses received.
13425930707SCorey Minyard 	 */
13525930707SCorey Minyard 	SSIF_STAT_received_messages,
13625930707SCorey Minyard 
13725930707SCorey Minyard 	/*
13825930707SCorey Minyard 	 * Number of message fragments received.
13925930707SCorey Minyard 	 */
14025930707SCorey Minyard 	SSIF_STAT_received_message_parts,
14125930707SCorey Minyard 
14225930707SCorey Minyard 	/*
14325930707SCorey Minyard 	 * Number of times the receive of a message was retried.
14425930707SCorey Minyard 	 */
14525930707SCorey Minyard 	SSIF_STAT_receive_retries,
14625930707SCorey Minyard 
14725930707SCorey Minyard 	/*
14825930707SCorey Minyard 	 * Number of errors receiving messages.
14925930707SCorey Minyard 	 */
15025930707SCorey Minyard 	SSIF_STAT_receive_errors,
15125930707SCorey Minyard 
15225930707SCorey Minyard 	/*
15325930707SCorey Minyard 	 * Number of times a flag fetch was requested.
15425930707SCorey Minyard 	 */
15525930707SCorey Minyard 	SSIF_STAT_flag_fetches,
15625930707SCorey Minyard 
15725930707SCorey Minyard 	/*
15825930707SCorey Minyard 	 * Number of times the hardware didn't follow the state machine.
15925930707SCorey Minyard 	 */
16025930707SCorey Minyard 	SSIF_STAT_hosed,
16125930707SCorey Minyard 
16225930707SCorey Minyard 	/*
16325930707SCorey Minyard 	 * Number of received events.
16425930707SCorey Minyard 	 */
16525930707SCorey Minyard 	SSIF_STAT_events,
16625930707SCorey Minyard 
16725930707SCorey Minyard 	/* Number of asyncronous messages received. */
16825930707SCorey Minyard 	SSIF_STAT_incoming_messages,
16925930707SCorey Minyard 
17025930707SCorey Minyard 	/* Number of watchdog pretimeouts. */
17125930707SCorey Minyard 	SSIF_STAT_watchdog_pretimeouts,
17225930707SCorey Minyard 
17391620521SCorey Minyard 	/* Number of alers received. */
17491620521SCorey Minyard 	SSIF_STAT_alerts,
17591620521SCorey Minyard 
17625930707SCorey Minyard 	/* Always add statistics before this value, it must be last. */
17725930707SCorey Minyard 	SSIF_NUM_STATS
17825930707SCorey Minyard };
17925930707SCorey Minyard 
18025930707SCorey Minyard struct ssif_addr_info {
18125930707SCorey Minyard 	struct i2c_board_info binfo;
18225930707SCorey Minyard 	char *adapter_name;
18325930707SCorey Minyard 	int debug;
18425930707SCorey Minyard 	int slave_addr;
18525930707SCorey Minyard 	enum ipmi_addr_src addr_src;
18625930707SCorey Minyard 	union ipmi_smi_info_union addr_info;
1870944d889SCorey Minyard 	struct device *dev;
1880944d889SCorey Minyard 	struct i2c_client *client;
18925930707SCorey Minyard 
19025930707SCorey Minyard 	struct mutex clients_mutex;
19125930707SCorey Minyard 	struct list_head clients;
19225930707SCorey Minyard 
19325930707SCorey Minyard 	struct list_head link;
19425930707SCorey Minyard };
19525930707SCorey Minyard 
19625930707SCorey Minyard struct ssif_info;
19725930707SCorey Minyard 
19825930707SCorey Minyard typedef void (*ssif_i2c_done)(struct ssif_info *ssif_info, int result,
19925930707SCorey Minyard 			     unsigned char *data, unsigned int len);
20025930707SCorey Minyard 
20125930707SCorey Minyard struct ssif_info {
202a567b623SCorey Minyard 	struct ipmi_smi     *intf;
20325930707SCorey Minyard 	spinlock_t	    lock;
20425930707SCorey Minyard 	struct ipmi_smi_msg *waiting_msg;
20525930707SCorey Minyard 	struct ipmi_smi_msg *curr_msg;
20625930707SCorey Minyard 	enum ssif_intf_state ssif_state;
20725930707SCorey Minyard 	unsigned long       ssif_debug;
20825930707SCorey Minyard 
20925930707SCorey Minyard 	struct ipmi_smi_handlers handlers;
21025930707SCorey Minyard 
21125930707SCorey Minyard 	enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */
21225930707SCorey Minyard 	union ipmi_smi_info_union addr_info;
21325930707SCorey Minyard 
21425930707SCorey Minyard 	/*
21525930707SCorey Minyard 	 * Flags from the last GET_MSG_FLAGS command, used when an ATTN
21625930707SCorey Minyard 	 * is set to hold the flags until we are done handling everything
21725930707SCorey Minyard 	 * from the flags.
21825930707SCorey Minyard 	 */
21925930707SCorey Minyard #define RECEIVE_MSG_AVAIL	0x01
22025930707SCorey Minyard #define EVENT_MSG_BUFFER_FULL	0x02
22125930707SCorey Minyard #define WDT_PRE_TIMEOUT_INT	0x08
22225930707SCorey Minyard 	unsigned char       msg_flags;
22325930707SCorey Minyard 
22491620521SCorey Minyard 	u8		    global_enables;
22525930707SCorey Minyard 	bool		    has_event_buffer;
22691620521SCorey Minyard 	bool		    supports_alert;
22791620521SCorey Minyard 
22891620521SCorey Minyard 	/*
22991620521SCorey Minyard 	 * Used to tell what we should do with alerts.  If we are
23091620521SCorey Minyard 	 * waiting on a response, read the data immediately.
23191620521SCorey Minyard 	 */
23291620521SCorey Minyard 	bool		    got_alert;
23391620521SCorey Minyard 	bool		    waiting_alert;
23425930707SCorey Minyard 
23500bb7e76SCorey Minyard 	/* Used to inform the timeout that it should do a resend. */
23600bb7e76SCorey Minyard 	bool		    do_resend;
23700bb7e76SCorey Minyard 
23825930707SCorey Minyard 	/*
23925930707SCorey Minyard 	 * If set to true, this will request events the next time the
24025930707SCorey Minyard 	 * state machine is idle.
24125930707SCorey Minyard 	 */
24225930707SCorey Minyard 	bool                req_events;
24325930707SCorey Minyard 
24425930707SCorey Minyard 	/*
24525930707SCorey Minyard 	 * If set to true, this will request flags the next time the
24625930707SCorey Minyard 	 * state machine is idle.
24725930707SCorey Minyard 	 */
24825930707SCorey Minyard 	bool                req_flags;
24925930707SCorey Minyard 
25025930707SCorey Minyard 	/* Used for sending/receiving data.  +1 for the length. */
25125930707SCorey Minyard 	unsigned char data[IPMI_MAX_MSG_LENGTH + 1];
25225930707SCorey Minyard 	unsigned int  data_len;
25325930707SCorey Minyard 
25425930707SCorey Minyard 	/* Temp receive buffer, gets copied into data. */
25525930707SCorey Minyard 	unsigned char recv[I2C_SMBUS_BLOCK_MAX];
25625930707SCorey Minyard 
25725930707SCorey Minyard 	struct i2c_client *client;
25825930707SCorey Minyard 	ssif_i2c_done done_handler;
25925930707SCorey Minyard 
26025930707SCorey Minyard 	/* Thread interface handling */
26125930707SCorey Minyard 	struct task_struct *thread;
26225930707SCorey Minyard 	struct completion wake_thread;
26325930707SCorey Minyard 	bool stopping;
26425930707SCorey Minyard 	int i2c_read_write;
26525930707SCorey Minyard 	int i2c_command;
26625930707SCorey Minyard 	unsigned char *i2c_data;
26725930707SCorey Minyard 	unsigned int i2c_size;
26825930707SCorey Minyard 
26925930707SCorey Minyard 	struct timer_list retry_timer;
27025930707SCorey Minyard 	int retries_left;
27125930707SCorey Minyard 
272c65ea996SCorey Minyard 	long watch_timeout;		/* Timeout for flags check, 0 if off. */
273a1466ec5SCorey Minyard 	struct timer_list watch_timer;	/* Flag fetch timer. */
274a1466ec5SCorey Minyard 
27525930707SCorey Minyard 	/* Info from SSIF cmd */
27625930707SCorey Minyard 	unsigned char max_xmit_msg_size;
27725930707SCorey Minyard 	unsigned char max_recv_msg_size;
27810042504SCorey Minyard 	bool cmd8_works; /* See test_multipart_messages() for details. */
27925930707SCorey Minyard 	unsigned int  multi_support;
28025930707SCorey Minyard 	int           supports_pec;
28125930707SCorey Minyard 
28225930707SCorey Minyard #define SSIF_NO_MULTI		0
28325930707SCorey Minyard #define SSIF_MULTI_2_PART	1
28425930707SCorey Minyard #define SSIF_MULTI_n_PART	2
28525930707SCorey Minyard 	unsigned char *multi_data;
28625930707SCorey Minyard 	unsigned int  multi_len;
28725930707SCorey Minyard 	unsigned int  multi_pos;
28825930707SCorey Minyard 
28925930707SCorey Minyard 	atomic_t stats[SSIF_NUM_STATS];
29025930707SCorey Minyard };
29125930707SCorey Minyard 
29225930707SCorey Minyard #define ssif_inc_stat(ssif, stat) \
29325930707SCorey Minyard 	atomic_inc(&(ssif)->stats[SSIF_STAT_ ## stat])
29425930707SCorey Minyard #define ssif_get_stat(ssif, stat) \
29525930707SCorey Minyard 	((unsigned int) atomic_read(&(ssif)->stats[SSIF_STAT_ ## stat]))
29625930707SCorey Minyard 
29725930707SCorey Minyard static bool initialized;
2982cd0e544SKefeng Wang static bool platform_registered;
29925930707SCorey Minyard 
30025930707SCorey Minyard static void return_hosed_msg(struct ssif_info *ssif_info,
30125930707SCorey Minyard 			     struct ipmi_smi_msg *msg);
30225930707SCorey Minyard static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags);
30325930707SCorey Minyard static int start_send(struct ssif_info *ssif_info,
30425930707SCorey Minyard 		      unsigned char   *data,
30525930707SCorey Minyard 		      unsigned int    len);
30625930707SCorey Minyard 
ipmi_ssif_lock_cond(struct ssif_info * ssif_info,unsigned long * flags)30725930707SCorey Minyard static unsigned long *ipmi_ssif_lock_cond(struct ssif_info *ssif_info,
30825930707SCorey Minyard 					  unsigned long *flags)
309562bf770SJules Irenge 	__acquires(&ssif_info->lock)
31025930707SCorey Minyard {
31125930707SCorey Minyard 	spin_lock_irqsave(&ssif_info->lock, *flags);
31225930707SCorey Minyard 	return flags;
31325930707SCorey Minyard }
31425930707SCorey Minyard 
ipmi_ssif_unlock_cond(struct ssif_info * ssif_info,unsigned long * flags)31525930707SCorey Minyard static void ipmi_ssif_unlock_cond(struct ssif_info *ssif_info,
31625930707SCorey Minyard 				  unsigned long *flags)
317562bf770SJules Irenge 	__releases(&ssif_info->lock)
31825930707SCorey Minyard {
31925930707SCorey Minyard 	spin_unlock_irqrestore(&ssif_info->lock, *flags);
32025930707SCorey Minyard }
32125930707SCorey Minyard 
deliver_recv_msg(struct ssif_info * ssif_info,struct ipmi_smi_msg * msg)32225930707SCorey Minyard static void deliver_recv_msg(struct ssif_info *ssif_info,
32325930707SCorey Minyard 			     struct ipmi_smi_msg *msg)
32425930707SCorey Minyard {
3250fbecb4fSCorey Minyard 	if (msg->rsp_size < 0) {
32625930707SCorey Minyard 		return_hosed_msg(ssif_info, msg);
32783af4194SCorey Minyard 		dev_err(&ssif_info->client->dev,
32883af4194SCorey Minyard 			"%s: Malformed message: rsp_size = %d\n",
32925880f7dSJoe Perches 		       __func__, msg->rsp_size);
33025930707SCorey Minyard 	} else {
3310fbecb4fSCorey Minyard 		ipmi_smi_msg_received(ssif_info->intf, msg);
33225930707SCorey Minyard 	}
33325930707SCorey Minyard }
33425930707SCorey Minyard 
return_hosed_msg(struct ssif_info * ssif_info,struct ipmi_smi_msg * msg)33525930707SCorey Minyard static void return_hosed_msg(struct ssif_info *ssif_info,
33625930707SCorey Minyard 			     struct ipmi_smi_msg *msg)
33725930707SCorey Minyard {
33825930707SCorey Minyard 	ssif_inc_stat(ssif_info, hosed);
33925930707SCorey Minyard 
34025930707SCorey Minyard 	/* Make it a response */
34125930707SCorey Minyard 	msg->rsp[0] = msg->data[0] | 4;
34225930707SCorey Minyard 	msg->rsp[1] = msg->data[1];
34325930707SCorey Minyard 	msg->rsp[2] = 0xFF; /* Unknown error. */
34425930707SCorey Minyard 	msg->rsp_size = 3;
34525930707SCorey Minyard 
34625930707SCorey Minyard 	deliver_recv_msg(ssif_info, msg);
34725930707SCorey Minyard }
34825930707SCorey Minyard 
34925930707SCorey Minyard /*
35025930707SCorey Minyard  * Must be called with the message lock held.  This will release the
3518230831cSCorey Minyard  * message lock.  Note that the caller will check IS_SSIF_IDLE and
3528230831cSCorey Minyard  * start a new operation, so there is no need to check for new
3538230831cSCorey Minyard  * messages to start in here.
35425930707SCorey Minyard  */
start_clear_flags(struct ssif_info * ssif_info,unsigned long * flags)35525930707SCorey Minyard static void start_clear_flags(struct ssif_info *ssif_info, unsigned long *flags)
35625930707SCorey Minyard {
35725930707SCorey Minyard 	unsigned char msg[3];
35825930707SCorey Minyard 
35925930707SCorey Minyard 	ssif_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
36025930707SCorey Minyard 	ssif_info->ssif_state = SSIF_CLEARING_FLAGS;
36125930707SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
36225930707SCorey Minyard 
36325930707SCorey Minyard 	/* Make sure the watchdog pre-timeout flag is not set at startup. */
36425930707SCorey Minyard 	msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
36525930707SCorey Minyard 	msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
36625930707SCorey Minyard 	msg[2] = WDT_PRE_TIMEOUT_INT;
36725930707SCorey Minyard 
36825930707SCorey Minyard 	if (start_send(ssif_info, msg, 3) != 0) {
36925930707SCorey Minyard 		/* Error, just go to normal state. */
3708230831cSCorey Minyard 		ssif_info->ssif_state = SSIF_IDLE;
37125930707SCorey Minyard 	}
37225930707SCorey Minyard }
37325930707SCorey Minyard 
start_flag_fetch(struct ssif_info * ssif_info,unsigned long * flags)37425930707SCorey Minyard static void start_flag_fetch(struct ssif_info *ssif_info, unsigned long *flags)
37525930707SCorey Minyard {
37625930707SCorey Minyard 	unsigned char mb[2];
37725930707SCorey Minyard 
37825930707SCorey Minyard 	ssif_info->req_flags = false;
37925930707SCorey Minyard 	ssif_info->ssif_state = SSIF_GETTING_FLAGS;
38025930707SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
38125930707SCorey Minyard 
38225930707SCorey Minyard 	mb[0] = (IPMI_NETFN_APP_REQUEST << 2);
38325930707SCorey Minyard 	mb[1] = IPMI_GET_MSG_FLAGS_CMD;
38425930707SCorey Minyard 	if (start_send(ssif_info, mb, 2) != 0)
3858230831cSCorey Minyard 		ssif_info->ssif_state = SSIF_IDLE;
38625930707SCorey Minyard }
38725930707SCorey Minyard 
check_start_send(struct ssif_info * ssif_info,unsigned long * flags,struct ipmi_smi_msg * msg)38825930707SCorey Minyard static void check_start_send(struct ssif_info *ssif_info, unsigned long *flags,
38925930707SCorey Minyard 			     struct ipmi_smi_msg *msg)
39025930707SCorey Minyard {
39125930707SCorey Minyard 	if (start_send(ssif_info, msg->data, msg->data_size) != 0) {
39225930707SCorey Minyard 		unsigned long oflags;
39325930707SCorey Minyard 
39425930707SCorey Minyard 		flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
39525930707SCorey Minyard 		ssif_info->curr_msg = NULL;
3968230831cSCorey Minyard 		ssif_info->ssif_state = SSIF_IDLE;
39725930707SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
39825930707SCorey Minyard 		ipmi_free_smi_msg(msg);
39925930707SCorey Minyard 	}
40025930707SCorey Minyard }
40125930707SCorey Minyard 
start_event_fetch(struct ssif_info * ssif_info,unsigned long * flags)40225930707SCorey Minyard static void start_event_fetch(struct ssif_info *ssif_info, unsigned long *flags)
40325930707SCorey Minyard {
40425930707SCorey Minyard 	struct ipmi_smi_msg *msg;
40525930707SCorey Minyard 
40625930707SCorey Minyard 	ssif_info->req_events = false;
40725930707SCorey Minyard 
40825930707SCorey Minyard 	msg = ipmi_alloc_smi_msg();
40925930707SCorey Minyard 	if (!msg) {
4108230831cSCorey Minyard 		ssif_info->ssif_state = SSIF_IDLE;
411cf9806f3SDan Carpenter 		ipmi_ssif_unlock_cond(ssif_info, flags);
41225930707SCorey Minyard 		return;
41325930707SCorey Minyard 	}
41425930707SCorey Minyard 
41525930707SCorey Minyard 	ssif_info->curr_msg = msg;
41625930707SCorey Minyard 	ssif_info->ssif_state = SSIF_GETTING_EVENTS;
41725930707SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
41825930707SCorey Minyard 
41925930707SCorey Minyard 	msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
42025930707SCorey Minyard 	msg->data[1] = IPMI_READ_EVENT_MSG_BUFFER_CMD;
42125930707SCorey Minyard 	msg->data_size = 2;
42225930707SCorey Minyard 
42325930707SCorey Minyard 	check_start_send(ssif_info, flags, msg);
42425930707SCorey Minyard }
42525930707SCorey Minyard 
start_recv_msg_fetch(struct ssif_info * ssif_info,unsigned long * flags)42625930707SCorey Minyard static void start_recv_msg_fetch(struct ssif_info *ssif_info,
42725930707SCorey Minyard 				 unsigned long *flags)
42825930707SCorey Minyard {
42925930707SCorey Minyard 	struct ipmi_smi_msg *msg;
43025930707SCorey Minyard 
43125930707SCorey Minyard 	msg = ipmi_alloc_smi_msg();
43225930707SCorey Minyard 	if (!msg) {
4338230831cSCorey Minyard 		ssif_info->ssif_state = SSIF_IDLE;
434cf9806f3SDan Carpenter 		ipmi_ssif_unlock_cond(ssif_info, flags);
43525930707SCorey Minyard 		return;
43625930707SCorey Minyard 	}
43725930707SCorey Minyard 
43825930707SCorey Minyard 	ssif_info->curr_msg = msg;
43925930707SCorey Minyard 	ssif_info->ssif_state = SSIF_GETTING_MESSAGES;
44025930707SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
44125930707SCorey Minyard 
44225930707SCorey Minyard 	msg->data[0] = (IPMI_NETFN_APP_REQUEST << 2);
44325930707SCorey Minyard 	msg->data[1] = IPMI_GET_MSG_CMD;
44425930707SCorey Minyard 	msg->data_size = 2;
44525930707SCorey Minyard 
44625930707SCorey Minyard 	check_start_send(ssif_info, flags, msg);
44725930707SCorey Minyard }
44825930707SCorey Minyard 
44925930707SCorey Minyard /*
45025930707SCorey Minyard  * Must be called with the message lock held.  This will release the
4518230831cSCorey Minyard  * message lock.  Note that the caller will check IS_SSIF_IDLE and
4528230831cSCorey Minyard  * start a new operation, so there is no need to check for new
4538230831cSCorey Minyard  * messages to start in here.
45425930707SCorey Minyard  */
handle_flags(struct ssif_info * ssif_info,unsigned long * flags)45525930707SCorey Minyard static void handle_flags(struct ssif_info *ssif_info, unsigned long *flags)
45625930707SCorey Minyard {
45725930707SCorey Minyard 	if (ssif_info->msg_flags & WDT_PRE_TIMEOUT_INT) {
45825930707SCorey Minyard 		/* Watchdog pre-timeout */
45925930707SCorey Minyard 		ssif_inc_stat(ssif_info, watchdog_pretimeouts);
46025930707SCorey Minyard 		start_clear_flags(ssif_info, flags);
4610fbecb4fSCorey Minyard 		ipmi_smi_watchdog_pretimeout(ssif_info->intf);
46225930707SCorey Minyard 	} else if (ssif_info->msg_flags & RECEIVE_MSG_AVAIL)
46325930707SCorey Minyard 		/* Messages available. */
46425930707SCorey Minyard 		start_recv_msg_fetch(ssif_info, flags);
46525930707SCorey Minyard 	else if (ssif_info->msg_flags & EVENT_MSG_BUFFER_FULL)
46625930707SCorey Minyard 		/* Events available. */
46725930707SCorey Minyard 		start_event_fetch(ssif_info, flags);
46825930707SCorey Minyard 	else {
4698230831cSCorey Minyard 		ssif_info->ssif_state = SSIF_IDLE;
47025930707SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
47125930707SCorey Minyard 	}
47225930707SCorey Minyard }
47325930707SCorey Minyard 
ipmi_ssif_thread(void * data)47425930707SCorey Minyard static int ipmi_ssif_thread(void *data)
47525930707SCorey Minyard {
47625930707SCorey Minyard 	struct ssif_info *ssif_info = data;
47725930707SCorey Minyard 
47825930707SCorey Minyard 	while (!kthread_should_stop()) {
47925930707SCorey Minyard 		int result;
48025930707SCorey Minyard 
48125930707SCorey Minyard 		/* Wait for something to do */
482d0acf734SCorey Minyard 		result = wait_for_completion_interruptible(
483d0acf734SCorey Minyard 						&ssif_info->wake_thread);
48425930707SCorey Minyard 		if (ssif_info->stopping)
48525930707SCorey Minyard 			break;
486d0acf734SCorey Minyard 		if (result == -ERESTARTSYS)
487d0acf734SCorey Minyard 			continue;
488d0acf734SCorey Minyard 		init_completion(&ssif_info->wake_thread);
48925930707SCorey Minyard 
49025930707SCorey Minyard 		if (ssif_info->i2c_read_write == I2C_SMBUS_WRITE) {
49125930707SCorey Minyard 			result = i2c_smbus_write_block_data(
4923d69d43bSCorey Minyard 				ssif_info->client, ssif_info->i2c_command,
49325930707SCorey Minyard 				ssif_info->i2c_data[0],
49425930707SCorey Minyard 				ssif_info->i2c_data + 1);
49525930707SCorey Minyard 			ssif_info->done_handler(ssif_info, result, NULL, 0);
49625930707SCorey Minyard 		} else {
49725930707SCorey Minyard 			result = i2c_smbus_read_block_data(
4983d69d43bSCorey Minyard 				ssif_info->client, ssif_info->i2c_command,
49925930707SCorey Minyard 				ssif_info->i2c_data);
50025930707SCorey Minyard 			if (result < 0)
50125930707SCorey Minyard 				ssif_info->done_handler(ssif_info, result,
50225930707SCorey Minyard 							NULL, 0);
50325930707SCorey Minyard 			else
50425930707SCorey Minyard 				ssif_info->done_handler(ssif_info, 0,
50525930707SCorey Minyard 							ssif_info->i2c_data,
50625930707SCorey Minyard 							result);
50725930707SCorey Minyard 		}
50825930707SCorey Minyard 	}
50925930707SCorey Minyard 
51025930707SCorey Minyard 	return 0;
51125930707SCorey Minyard }
51225930707SCorey Minyard 
ssif_i2c_send(struct ssif_info * ssif_info,ssif_i2c_done handler,int read_write,int command,unsigned char * data,unsigned int size)513dcd10526SLiguang Zhang static void ssif_i2c_send(struct ssif_info *ssif_info,
51425930707SCorey Minyard 			ssif_i2c_done handler,
51525930707SCorey Minyard 			int read_write, int command,
51625930707SCorey Minyard 			unsigned char *data, unsigned int size)
51725930707SCorey Minyard {
51825930707SCorey Minyard 	ssif_info->done_handler = handler;
51925930707SCorey Minyard 
52025930707SCorey Minyard 	ssif_info->i2c_read_write = read_write;
52125930707SCorey Minyard 	ssif_info->i2c_command = command;
52225930707SCorey Minyard 	ssif_info->i2c_data = data;
52325930707SCorey Minyard 	ssif_info->i2c_size = size;
52425930707SCorey Minyard 	complete(&ssif_info->wake_thread);
52525930707SCorey Minyard }
52625930707SCorey Minyard 
52725930707SCorey Minyard 
52825930707SCorey Minyard static void msg_done_handler(struct ssif_info *ssif_info, int result,
52925930707SCorey Minyard 			     unsigned char *data, unsigned int len);
53025930707SCorey Minyard 
start_get(struct ssif_info * ssif_info)53191620521SCorey Minyard static void start_get(struct ssif_info *ssif_info)
53225930707SCorey Minyard {
5333d69d43bSCorey Minyard 	ssif_info->multi_pos = 0;
53425930707SCorey Minyard 
535dcd10526SLiguang Zhang 	ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ,
53625930707SCorey Minyard 		  SSIF_IPMI_RESPONSE,
53725930707SCorey Minyard 		  ssif_info->recv, I2C_SMBUS_BLOCK_DATA);
53825930707SCorey Minyard }
53925930707SCorey Minyard 
54000bb7e76SCorey Minyard static void start_resend(struct ssif_info *ssif_info);
54100bb7e76SCorey Minyard 
retry_timeout(struct timer_list * t)542e99e88a9SKees Cook static void retry_timeout(struct timer_list *t)
54391620521SCorey Minyard {
544e99e88a9SKees Cook 	struct ssif_info *ssif_info = from_timer(ssif_info, t, retry_timer);
54591620521SCorey Minyard 	unsigned long oflags, *flags;
54600bb7e76SCorey Minyard 	bool waiting, resend;
54791620521SCorey Minyard 
54891620521SCorey Minyard 	if (ssif_info->stopping)
54991620521SCorey Minyard 		return;
55091620521SCorey Minyard 
55191620521SCorey Minyard 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
55200bb7e76SCorey Minyard 	resend = ssif_info->do_resend;
55300bb7e76SCorey Minyard 	ssif_info->do_resend = false;
55491620521SCorey Minyard 	waiting = ssif_info->waiting_alert;
55591620521SCorey Minyard 	ssif_info->waiting_alert = false;
55691620521SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
55791620521SCorey Minyard 
55891620521SCorey Minyard 	if (waiting)
55991620521SCorey Minyard 		start_get(ssif_info);
5606ce7995aSCorey Minyard 	if (resend) {
56100bb7e76SCorey Minyard 		start_resend(ssif_info);
5626ce7995aSCorey Minyard 		ssif_inc_stat(ssif_info, send_retries);
5636ce7995aSCorey Minyard 	}
56491620521SCorey Minyard }
56591620521SCorey Minyard 
watch_timeout(struct timer_list * t)566a1466ec5SCorey Minyard static void watch_timeout(struct timer_list *t)
567a1466ec5SCorey Minyard {
568a1466ec5SCorey Minyard 	struct ssif_info *ssif_info = from_timer(ssif_info, t, watch_timer);
569a1466ec5SCorey Minyard 	unsigned long oflags, *flags;
570a1466ec5SCorey Minyard 
571a1466ec5SCorey Minyard 	if (ssif_info->stopping)
572a1466ec5SCorey Minyard 		return;
573a1466ec5SCorey Minyard 
574a1466ec5SCorey Minyard 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
575c65ea996SCorey Minyard 	if (ssif_info->watch_timeout) {
576a1466ec5SCorey Minyard 		mod_timer(&ssif_info->watch_timer,
577c65ea996SCorey Minyard 			  jiffies + ssif_info->watch_timeout);
5788230831cSCorey Minyard 		if (IS_SSIF_IDLE(ssif_info)) {
579a1466ec5SCorey Minyard 			start_flag_fetch(ssif_info, flags); /* Releases lock */
580a1466ec5SCorey Minyard 			return;
581a1466ec5SCorey Minyard 		}
582a1466ec5SCorey Minyard 		ssif_info->req_flags = true;
583a1466ec5SCorey Minyard 	}
584a1466ec5SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
585a1466ec5SCorey Minyard }
58691620521SCorey Minyard 
ssif_alert(struct i2c_client * client,enum i2c_alert_protocol type,unsigned int data)587b4f21054SBenjamin Tissoires static void ssif_alert(struct i2c_client *client, enum i2c_alert_protocol type,
588b4f21054SBenjamin Tissoires 		       unsigned int data)
58991620521SCorey Minyard {
59091620521SCorey Minyard 	struct ssif_info *ssif_info = i2c_get_clientdata(client);
59191620521SCorey Minyard 	unsigned long oflags, *flags;
59291620521SCorey Minyard 	bool do_get = false;
59391620521SCorey Minyard 
594b4f21054SBenjamin Tissoires 	if (type != I2C_PROTOCOL_SMBUS_ALERT)
595b4f21054SBenjamin Tissoires 		return;
596b4f21054SBenjamin Tissoires 
59791620521SCorey Minyard 	ssif_inc_stat(ssif_info, alerts);
59891620521SCorey Minyard 
59991620521SCorey Minyard 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
60091620521SCorey Minyard 	if (ssif_info->waiting_alert) {
60191620521SCorey Minyard 		ssif_info->waiting_alert = false;
60291620521SCorey Minyard 		del_timer(&ssif_info->retry_timer);
60391620521SCorey Minyard 		do_get = true;
60491620521SCorey Minyard 	} else if (ssif_info->curr_msg) {
60591620521SCorey Minyard 		ssif_info->got_alert = true;
60691620521SCorey Minyard 	}
60791620521SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
60891620521SCorey Minyard 	if (do_get)
60991620521SCorey Minyard 		start_get(ssif_info);
61091620521SCorey Minyard }
61191620521SCorey Minyard 
msg_done_handler(struct ssif_info * ssif_info,int result,unsigned char * data,unsigned int len)61225930707SCorey Minyard static void msg_done_handler(struct ssif_info *ssif_info, int result,
61325930707SCorey Minyard 			     unsigned char *data, unsigned int len)
61425930707SCorey Minyard {
61525930707SCorey Minyard 	struct ipmi_smi_msg *msg;
61625930707SCorey Minyard 	unsigned long oflags, *flags;
61725930707SCorey Minyard 
61825930707SCorey Minyard 	/*
61925930707SCorey Minyard 	 * We are single-threaded here, so no need for a lock until we
62025930707SCorey Minyard 	 * start messing with driver states or the queues.
62125930707SCorey Minyard 	 */
62225930707SCorey Minyard 
62325930707SCorey Minyard 	if (result < 0) {
62425930707SCorey Minyard 		ssif_info->retries_left--;
62525930707SCorey Minyard 		if (ssif_info->retries_left > 0) {
62625930707SCorey Minyard 			ssif_inc_stat(ssif_info, receive_retries);
62725930707SCorey Minyard 
62891620521SCorey Minyard 			flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
62991620521SCorey Minyard 			ssif_info->waiting_alert = true;
6300711e8c1SJan Glauber 			if (!ssif_info->stopping)
63125930707SCorey Minyard 				mod_timer(&ssif_info->retry_timer,
63225930707SCorey Minyard 					  jiffies + SSIF_MSG_JIFFIES);
63391620521SCorey Minyard 			ipmi_ssif_unlock_cond(ssif_info, flags);
63425930707SCorey Minyard 			return;
63525930707SCorey Minyard 		}
63625930707SCorey Minyard 
63725930707SCorey Minyard 		ssif_inc_stat(ssif_info, receive_errors);
63825930707SCorey Minyard 
63925930707SCorey Minyard 		if  (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
64083af4194SCorey Minyard 			dev_dbg(&ssif_info->client->dev,
64183af4194SCorey Minyard 				"%s: Error %d\n", __func__, result);
64225930707SCorey Minyard 		len = 0;
64325930707SCorey Minyard 		goto continue_op;
64425930707SCorey Minyard 	}
64525930707SCorey Minyard 
64625930707SCorey Minyard 	if ((len > 1) && (ssif_info->multi_pos == 0)
64725930707SCorey Minyard 				&& (data[0] == 0x00) && (data[1] == 0x01)) {
64825930707SCorey Minyard 		/* Start of multi-part read.  Start the next transaction. */
64925930707SCorey Minyard 		int i;
65025930707SCorey Minyard 
65125930707SCorey Minyard 		ssif_inc_stat(ssif_info, received_message_parts);
65225930707SCorey Minyard 
65325930707SCorey Minyard 		/* Remove the multi-part read marker. */
65425930707SCorey Minyard 		len -= 2;
6557d6380cdSCorey Minyard 		data += 2;
6563d69d43bSCorey Minyard 		for (i = 0; i < len; i++)
6577d6380cdSCorey Minyard 			ssif_info->data[i] = data[i];
65825930707SCorey Minyard 		ssif_info->multi_len = len;
65925930707SCorey Minyard 		ssif_info->multi_pos = 1;
66025930707SCorey Minyard 
661dcd10526SLiguang Zhang 		ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ,
66225930707SCorey Minyard 			 SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE,
66325930707SCorey Minyard 			 ssif_info->recv, I2C_SMBUS_BLOCK_DATA);
66425930707SCorey Minyard 		return;
66525930707SCorey Minyard 	} else if (ssif_info->multi_pos) {
66625930707SCorey Minyard 		/* Middle of multi-part read.  Start the next transaction. */
66725930707SCorey Minyard 		int i;
66825930707SCorey Minyard 		unsigned char blocknum;
66925930707SCorey Minyard 
67025930707SCorey Minyard 		if (len == 0) {
67125930707SCorey Minyard 			result = -EIO;
67225930707SCorey Minyard 			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
67383af4194SCorey Minyard 				dev_dbg(&ssif_info->client->dev,
67483af4194SCorey Minyard 					"Middle message with no data\n");
67525930707SCorey Minyard 
67625930707SCorey Minyard 			goto continue_op;
67725930707SCorey Minyard 		}
67825930707SCorey Minyard 
6793d69d43bSCorey Minyard 		blocknum = data[0];
6807d6380cdSCorey Minyard 		len--;
6817d6380cdSCorey Minyard 		data++;
68225930707SCorey Minyard 
6837d6380cdSCorey Minyard 		if (blocknum != 0xff && len != 31) {
6847d6380cdSCorey Minyard 		    /* All blocks but the last must have 31 data bytes. */
6857d6380cdSCorey Minyard 			result = -EIO;
6867d6380cdSCorey Minyard 			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
68783af4194SCorey Minyard 				dev_dbg(&ssif_info->client->dev,
68883af4194SCorey Minyard 					"Received middle message <31\n");
6897d6380cdSCorey Minyard 
6907d6380cdSCorey Minyard 			goto continue_op;
6917d6380cdSCorey Minyard 		}
6927d6380cdSCorey Minyard 
6937d6380cdSCorey Minyard 		if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) {
69425930707SCorey Minyard 			/* Received message too big, abort the operation. */
69525930707SCorey Minyard 			result = -E2BIG;
69625930707SCorey Minyard 			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
69783af4194SCorey Minyard 				dev_dbg(&ssif_info->client->dev,
69883af4194SCorey Minyard 					"Received message too big\n");
69925930707SCorey Minyard 
70025930707SCorey Minyard 			goto continue_op;
70125930707SCorey Minyard 		}
70225930707SCorey Minyard 
7033d69d43bSCorey Minyard 		for (i = 0; i < len; i++)
7047d6380cdSCorey Minyard 			ssif_info->data[i + ssif_info->multi_len] = data[i];
70525930707SCorey Minyard 		ssif_info->multi_len += len;
70625930707SCorey Minyard 		if (blocknum == 0xff) {
70725930707SCorey Minyard 			/* End of read */
70825930707SCorey Minyard 			len = ssif_info->multi_len;
70925930707SCorey Minyard 			data = ssif_info->data;
71055be8658SKamlakant Patel 		} else if (blocknum + 1 != ssif_info->multi_pos) {
71125930707SCorey Minyard 			/*
71225930707SCorey Minyard 			 * Out of sequence block, just abort.  Block
71325930707SCorey Minyard 			 * numbers start at zero for the second block,
71425930707SCorey Minyard 			 * but multi_pos starts at one, so the +1.
71525930707SCorey Minyard 			 */
71655be8658SKamlakant Patel 			if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
71755be8658SKamlakant Patel 				dev_dbg(&ssif_info->client->dev,
71855be8658SKamlakant Patel 					"Received message out of sequence, expected %u, got %u\n",
71955be8658SKamlakant Patel 					ssif_info->multi_pos - 1, blocknum);
72025930707SCorey Minyard 			result = -EIO;
72125930707SCorey Minyard 		} else {
72225930707SCorey Minyard 			ssif_inc_stat(ssif_info, received_message_parts);
72325930707SCorey Minyard 
72425930707SCorey Minyard 			ssif_info->multi_pos++;
72525930707SCorey Minyard 
726dcd10526SLiguang Zhang 			ssif_i2c_send(ssif_info, msg_done_handler,
72725930707SCorey Minyard 				  I2C_SMBUS_READ,
72825930707SCorey Minyard 				  SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE,
72925930707SCorey Minyard 				  ssif_info->recv,
73025930707SCorey Minyard 				  I2C_SMBUS_BLOCK_DATA);
73125930707SCorey Minyard 			return;
73225930707SCorey Minyard 		}
73325930707SCorey Minyard 	}
73425930707SCorey Minyard 
7357d6380cdSCorey Minyard  continue_op:
73625930707SCorey Minyard 	if (result < 0) {
73725930707SCorey Minyard 		ssif_inc_stat(ssif_info, receive_errors);
73825930707SCorey Minyard 	} else {
73925930707SCorey Minyard 		ssif_inc_stat(ssif_info, received_messages);
74025930707SCorey Minyard 		ssif_inc_stat(ssif_info, received_message_parts);
74125930707SCorey Minyard 	}
74225930707SCorey Minyard 
74325930707SCorey Minyard 	if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
74483af4194SCorey Minyard 		dev_dbg(&ssif_info->client->dev,
74583af4194SCorey Minyard 			"DONE 1: state = %d, result=%d\n",
74625930707SCorey Minyard 			ssif_info->ssif_state, result);
74725930707SCorey Minyard 
74825930707SCorey Minyard 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
74925930707SCorey Minyard 	msg = ssif_info->curr_msg;
75025930707SCorey Minyard 	if (msg) {
7516b8526d3SCorey Minyard 		if (data) {
7526b8526d3SCorey Minyard 			if (len > IPMI_MAX_MSG_LENGTH)
7536b8526d3SCorey Minyard 				len = IPMI_MAX_MSG_LENGTH;
7546b8526d3SCorey Minyard 			memcpy(msg->rsp, data, len);
7556b8526d3SCorey Minyard 		} else {
7566b8526d3SCorey Minyard 			len = 0;
7576b8526d3SCorey Minyard 		}
75825930707SCorey Minyard 		msg->rsp_size = len;
75925930707SCorey Minyard 		ssif_info->curr_msg = NULL;
76025930707SCorey Minyard 	}
76125930707SCorey Minyard 
76225930707SCorey Minyard 	switch (ssif_info->ssif_state) {
7638230831cSCorey Minyard 	case SSIF_IDLE:
76425930707SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
76525930707SCorey Minyard 		if (!msg)
76625930707SCorey Minyard 			break;
76725930707SCorey Minyard 
76825930707SCorey Minyard 		if (result < 0)
76925930707SCorey Minyard 			return_hosed_msg(ssif_info, msg);
77025930707SCorey Minyard 		else
77125930707SCorey Minyard 			deliver_recv_msg(ssif_info, msg);
77225930707SCorey Minyard 		break;
77325930707SCorey Minyard 
77425930707SCorey Minyard 	case SSIF_GETTING_FLAGS:
77525930707SCorey Minyard 		/* We got the flags from the SSIF, now handle them. */
77625930707SCorey Minyard 		if ((result < 0) || (len < 4) || (data[2] != 0)) {
77725930707SCorey Minyard 			/*
77825930707SCorey Minyard 			 * Error fetching flags, or invalid length,
77925930707SCorey Minyard 			 * just give up for now.
78025930707SCorey Minyard 			 */
7818230831cSCorey Minyard 			ssif_info->ssif_state = SSIF_IDLE;
78225930707SCorey Minyard 			ipmi_ssif_unlock_cond(ssif_info, flags);
78383af4194SCorey Minyard 			dev_warn(&ssif_info->client->dev,
78483af4194SCorey Minyard 				 "Error getting flags: %d %d, %x\n",
785f002612bSKamlakant Patel 				 result, len, (len >= 3) ? data[2] : 0);
78625930707SCorey Minyard 		} else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2
78725930707SCorey Minyard 			   || data[1] != IPMI_GET_MSG_FLAGS_CMD) {
7884495ec6dSCorey Minyard 			/*
7896d2555cdSZhang Yuchen 			 * Recv error response, give up.
7904495ec6dSCorey Minyard 			 */
7916d2555cdSZhang Yuchen 			ssif_info->ssif_state = SSIF_IDLE;
7924495ec6dSCorey Minyard 			ipmi_ssif_unlock_cond(ssif_info, flags);
79383af4194SCorey Minyard 			dev_warn(&ssif_info->client->dev,
79483af4194SCorey Minyard 				 "Invalid response getting flags: %x %x\n",
79525930707SCorey Minyard 				 data[0], data[1]);
79625930707SCorey Minyard 		} else {
79725930707SCorey Minyard 			ssif_inc_stat(ssif_info, flag_fetches);
79825930707SCorey Minyard 			ssif_info->msg_flags = data[3];
79925930707SCorey Minyard 			handle_flags(ssif_info, flags);
80025930707SCorey Minyard 		}
80125930707SCorey Minyard 		break;
80225930707SCorey Minyard 
80325930707SCorey Minyard 	case SSIF_CLEARING_FLAGS:
80425930707SCorey Minyard 		/* We cleared the flags. */
80525930707SCorey Minyard 		if ((result < 0) || (len < 3) || (data[2] != 0)) {
80625930707SCorey Minyard 			/* Error clearing flags */
80783af4194SCorey Minyard 			dev_warn(&ssif_info->client->dev,
80883af4194SCorey Minyard 				 "Error clearing flags: %d %d, %x\n",
809f002612bSKamlakant Patel 				 result, len, (len >= 3) ? data[2] : 0);
81025930707SCorey Minyard 		} else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2
81125930707SCorey Minyard 			   || data[1] != IPMI_CLEAR_MSG_FLAGS_CMD) {
81283af4194SCorey Minyard 			dev_warn(&ssif_info->client->dev,
81383af4194SCorey Minyard 				 "Invalid response clearing flags: %x %x\n",
81425930707SCorey Minyard 				 data[0], data[1]);
81525930707SCorey Minyard 		}
8168230831cSCorey Minyard 		ssif_info->ssif_state = SSIF_IDLE;
81725930707SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
81825930707SCorey Minyard 		break;
81925930707SCorey Minyard 
82025930707SCorey Minyard 	case SSIF_GETTING_EVENTS:
8217602b957SCorey Minyard 		if (!msg) {
8227602b957SCorey Minyard 			/* Should never happen, but just in case. */
8237602b957SCorey Minyard 			dev_warn(&ssif_info->client->dev,
8247602b957SCorey Minyard 				 "No message set while getting events\n");
8257602b957SCorey Minyard 			ipmi_ssif_unlock_cond(ssif_info, flags);
8267602b957SCorey Minyard 			break;
8277602b957SCorey Minyard 		}
8287602b957SCorey Minyard 
82925930707SCorey Minyard 		if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) {
83025930707SCorey Minyard 			/* Error getting event, probably done. */
83125930707SCorey Minyard 			msg->done(msg);
83225930707SCorey Minyard 
83325930707SCorey Minyard 			/* Take off the event flag. */
83425930707SCorey Minyard 			ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
83525930707SCorey Minyard 			handle_flags(ssif_info, flags);
83625930707SCorey Minyard 		} else if (msg->rsp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2
83725930707SCorey Minyard 			   || msg->rsp[1] != IPMI_READ_EVENT_MSG_BUFFER_CMD) {
83883af4194SCorey Minyard 			dev_warn(&ssif_info->client->dev,
83983af4194SCorey Minyard 				 "Invalid response getting events: %x %x\n",
84025930707SCorey Minyard 				 msg->rsp[0], msg->rsp[1]);
84125930707SCorey Minyard 			msg->done(msg);
84225930707SCorey Minyard 			/* Take off the event flag. */
84325930707SCorey Minyard 			ssif_info->msg_flags &= ~EVENT_MSG_BUFFER_FULL;
84425930707SCorey Minyard 			handle_flags(ssif_info, flags);
84525930707SCorey Minyard 		} else {
84625930707SCorey Minyard 			handle_flags(ssif_info, flags);
84725930707SCorey Minyard 			ssif_inc_stat(ssif_info, events);
84825930707SCorey Minyard 			deliver_recv_msg(ssif_info, msg);
84925930707SCorey Minyard 		}
85025930707SCorey Minyard 		break;
85125930707SCorey Minyard 
85225930707SCorey Minyard 	case SSIF_GETTING_MESSAGES:
8537602b957SCorey Minyard 		if (!msg) {
8547602b957SCorey Minyard 			/* Should never happen, but just in case. */
8557602b957SCorey Minyard 			dev_warn(&ssif_info->client->dev,
8567602b957SCorey Minyard 				 "No message set while getting messages\n");
8577602b957SCorey Minyard 			ipmi_ssif_unlock_cond(ssif_info, flags);
8587602b957SCorey Minyard 			break;
8597602b957SCorey Minyard 		}
8607602b957SCorey Minyard 
86125930707SCorey Minyard 		if ((result < 0) || (len < 3) || (msg->rsp[2] != 0)) {
86225930707SCorey Minyard 			/* Error getting event, probably done. */
86325930707SCorey Minyard 			msg->done(msg);
86425930707SCorey Minyard 
86525930707SCorey Minyard 			/* Take off the msg flag. */
86625930707SCorey Minyard 			ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
86725930707SCorey Minyard 			handle_flags(ssif_info, flags);
86825930707SCorey Minyard 		} else if (msg->rsp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2
86925930707SCorey Minyard 			   || msg->rsp[1] != IPMI_GET_MSG_CMD) {
87083af4194SCorey Minyard 			dev_warn(&ssif_info->client->dev,
87183af4194SCorey Minyard 				 "Invalid response clearing flags: %x %x\n",
87225930707SCorey Minyard 				 msg->rsp[0], msg->rsp[1]);
87325930707SCorey Minyard 			msg->done(msg);
87425930707SCorey Minyard 
87525930707SCorey Minyard 			/* Take off the msg flag. */
87625930707SCorey Minyard 			ssif_info->msg_flags &= ~RECEIVE_MSG_AVAIL;
87725930707SCorey Minyard 			handle_flags(ssif_info, flags);
87825930707SCorey Minyard 		} else {
87925930707SCorey Minyard 			ssif_inc_stat(ssif_info, incoming_messages);
88025930707SCorey Minyard 			handle_flags(ssif_info, flags);
88125930707SCorey Minyard 			deliver_recv_msg(ssif_info, msg);
88225930707SCorey Minyard 		}
88325930707SCorey Minyard 		break;
8847602b957SCorey Minyard 
8857602b957SCorey Minyard 	default:
8867602b957SCorey Minyard 		/* Should never happen, but just in case. */
8877602b957SCorey Minyard 		dev_warn(&ssif_info->client->dev,
8887602b957SCorey Minyard 			 "Invalid state in message done handling: %d\n",
8897602b957SCorey Minyard 			 ssif_info->ssif_state);
8907602b957SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
89125930707SCorey Minyard 	}
89225930707SCorey Minyard 
89325930707SCorey Minyard 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
8948230831cSCorey Minyard 	if (IS_SSIF_IDLE(ssif_info) && !ssif_info->stopping) {
89525930707SCorey Minyard 		if (ssif_info->req_events)
89625930707SCorey Minyard 			start_event_fetch(ssif_info, flags);
89725930707SCorey Minyard 		else if (ssif_info->req_flags)
89825930707SCorey Minyard 			start_flag_fetch(ssif_info, flags);
89925930707SCorey Minyard 		else
90025930707SCorey Minyard 			start_next_msg(ssif_info, flags);
90125930707SCorey Minyard 	} else
90225930707SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
90325930707SCorey Minyard 
90425930707SCorey Minyard 	if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
90583af4194SCorey Minyard 		dev_dbg(&ssif_info->client->dev,
90683af4194SCorey Minyard 			"DONE 2: state = %d.\n", ssif_info->ssif_state);
90725930707SCorey Minyard }
90825930707SCorey Minyard 
msg_written_handler(struct ssif_info * ssif_info,int result,unsigned char * data,unsigned int len)90925930707SCorey Minyard static void msg_written_handler(struct ssif_info *ssif_info, int result,
91025930707SCorey Minyard 				unsigned char *data, unsigned int len)
91125930707SCorey Minyard {
91225930707SCorey Minyard 	/* We are single-threaded here, so no need for a lock. */
91325930707SCorey Minyard 	if (result < 0) {
91425930707SCorey Minyard 		ssif_info->retries_left--;
91525930707SCorey Minyard 		if (ssif_info->retries_left > 0) {
91600bb7e76SCorey Minyard 			/*
91700bb7e76SCorey Minyard 			 * Wait the retry timeout time per the spec,
91800bb7e76SCorey Minyard 			 * then redo the send.
91900bb7e76SCorey Minyard 			 */
92000bb7e76SCorey Minyard 			ssif_info->do_resend = true;
92100bb7e76SCorey Minyard 			mod_timer(&ssif_info->retry_timer,
92200bb7e76SCorey Minyard 				  jiffies + SSIF_REQ_RETRY_JIFFIES);
92325930707SCorey Minyard 			return;
92425930707SCorey Minyard 		}
92595767ed7SCorey Minyard 
92625930707SCorey Minyard 		ssif_inc_stat(ssif_info, send_errors);
92725930707SCorey Minyard 
92825930707SCorey Minyard 		if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
92983af4194SCorey Minyard 			dev_dbg(&ssif_info->client->dev,
93083af4194SCorey Minyard 				"%s: Out of retries\n", __func__);
93195767ed7SCorey Minyard 
93225930707SCorey Minyard 		msg_done_handler(ssif_info, -EIO, NULL, 0);
93325930707SCorey Minyard 		return;
93425930707SCorey Minyard 	}
93525930707SCorey Minyard 
93625930707SCorey Minyard 	if (ssif_info->multi_data) {
9373d69d43bSCorey Minyard 		/*
9383d69d43bSCorey Minyard 		 * In the middle of a multi-data write.  See the comment
9393d69d43bSCorey Minyard 		 * in the SSIF_MULTI_n_PART case in the probe function
9403d69d43bSCorey Minyard 		 * for details on the intricacies of this.
9413d69d43bSCorey Minyard 		 */
94210042504SCorey Minyard 		int left, to_write;
9436de65fcfSJoeseph Chang 		unsigned char *data_to_send;
94410042504SCorey Minyard 		unsigned char cmd;
94525930707SCorey Minyard 
94625930707SCorey Minyard 		ssif_inc_stat(ssif_info, sent_messages_parts);
94725930707SCorey Minyard 
94825930707SCorey Minyard 		left = ssif_info->multi_len - ssif_info->multi_pos;
94910042504SCorey Minyard 		to_write = left;
95010042504SCorey Minyard 		if (to_write > 32)
95110042504SCorey Minyard 			to_write = 32;
95225930707SCorey Minyard 		/* Length byte. */
95310042504SCorey Minyard 		ssif_info->multi_data[ssif_info->multi_pos] = to_write;
9546de65fcfSJoeseph Chang 		data_to_send = ssif_info->multi_data + ssif_info->multi_pos;
95510042504SCorey Minyard 		ssif_info->multi_pos += to_write;
95610042504SCorey Minyard 		cmd = SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE;
95710042504SCorey Minyard 		if (ssif_info->cmd8_works) {
95810042504SCorey Minyard 			if (left == to_write) {
95910042504SCorey Minyard 				cmd = SSIF_IPMI_MULTI_PART_REQUEST_END;
96025930707SCorey Minyard 				ssif_info->multi_data = NULL;
96110042504SCorey Minyard 			}
96210042504SCorey Minyard 		} else if (to_write < 32) {
96310042504SCorey Minyard 			ssif_info->multi_data = NULL;
96410042504SCorey Minyard 		}
96525930707SCorey Minyard 
966dcd10526SLiguang Zhang 		ssif_i2c_send(ssif_info, msg_written_handler,
96710042504SCorey Minyard 			  I2C_SMBUS_WRITE, cmd,
96810042504SCorey Minyard 			  data_to_send, I2C_SMBUS_BLOCK_DATA);
96925930707SCorey Minyard 	} else {
97021c8f915SCorey Minyard 		/* Ready to request the result. */
97191620521SCorey Minyard 		unsigned long oflags, *flags;
97291620521SCorey Minyard 
97325930707SCorey Minyard 		ssif_inc_stat(ssif_info, sent_messages);
97425930707SCorey Minyard 		ssif_inc_stat(ssif_info, sent_messages_parts);
97525930707SCorey Minyard 
97691620521SCorey Minyard 		flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
97721c8f915SCorey Minyard 		if (ssif_info->got_alert) {
97821c8f915SCorey Minyard 			/* The result is already ready, just start it. */
97991620521SCorey Minyard 			ssif_info->got_alert = false;
98091620521SCorey Minyard 			ipmi_ssif_unlock_cond(ssif_info, flags);
98121c8f915SCorey Minyard 			start_get(ssif_info);
98291620521SCorey Minyard 		} else {
98325930707SCorey Minyard 			/* Wait a jiffie then request the next message */
98491620521SCorey Minyard 			ssif_info->waiting_alert = true;
98525930707SCorey Minyard 			ssif_info->retries_left = SSIF_RECV_RETRIES;
9860711e8c1SJan Glauber 			if (!ssif_info->stopping)
98725930707SCorey Minyard 				mod_timer(&ssif_info->retry_timer,
98825930707SCorey Minyard 					  jiffies + SSIF_MSG_PART_JIFFIES);
98991620521SCorey Minyard 			ipmi_ssif_unlock_cond(ssif_info, flags);
99091620521SCorey Minyard 		}
99125930707SCorey Minyard 	}
99225930707SCorey Minyard }
99325930707SCorey Minyard 
start_resend(struct ssif_info * ssif_info)99495767ed7SCorey Minyard static void start_resend(struct ssif_info *ssif_info)
99525930707SCorey Minyard {
99625930707SCorey Minyard 	int command;
99725930707SCorey Minyard 
99891620521SCorey Minyard 	ssif_info->got_alert = false;
99991620521SCorey Minyard 
100025930707SCorey Minyard 	if (ssif_info->data_len > 32) {
100125930707SCorey Minyard 		command = SSIF_IPMI_MULTI_PART_REQUEST_START;
100225930707SCorey Minyard 		ssif_info->multi_data = ssif_info->data;
100325930707SCorey Minyard 		ssif_info->multi_len = ssif_info->data_len;
100425930707SCorey Minyard 		/*
100525930707SCorey Minyard 		 * Subtle thing, this is 32, not 33, because we will
100625930707SCorey Minyard 		 * overwrite the thing at position 32 (which was just
100725930707SCorey Minyard 		 * transmitted) with the new length.
100825930707SCorey Minyard 		 */
100925930707SCorey Minyard 		ssif_info->multi_pos = 32;
101025930707SCorey Minyard 		ssif_info->data[0] = 32;
101125930707SCorey Minyard 	} else {
101225930707SCorey Minyard 		ssif_info->multi_data = NULL;
101325930707SCorey Minyard 		command = SSIF_IPMI_REQUEST;
101425930707SCorey Minyard 		ssif_info->data[0] = ssif_info->data_len;
101525930707SCorey Minyard 	}
101625930707SCorey Minyard 
1017dcd10526SLiguang Zhang 	ssif_i2c_send(ssif_info, msg_written_handler, I2C_SMBUS_WRITE,
101825930707SCorey Minyard 		   command, ssif_info->data, I2C_SMBUS_BLOCK_DATA);
101925930707SCorey Minyard }
102025930707SCorey Minyard 
start_send(struct ssif_info * ssif_info,unsigned char * data,unsigned int len)102125930707SCorey Minyard static int start_send(struct ssif_info *ssif_info,
102225930707SCorey Minyard 		      unsigned char   *data,
102325930707SCorey Minyard 		      unsigned int    len)
102425930707SCorey Minyard {
102525930707SCorey Minyard 	if (len > IPMI_MAX_MSG_LENGTH)
102625930707SCorey Minyard 		return -E2BIG;
102725930707SCorey Minyard 	if (len > ssif_info->max_xmit_msg_size)
102825930707SCorey Minyard 		return -E2BIG;
102925930707SCorey Minyard 
103025930707SCorey Minyard 	ssif_info->retries_left = SSIF_SEND_RETRIES;
103125930707SCorey Minyard 	memcpy(ssif_info->data + 1, data, len);
103225930707SCorey Minyard 	ssif_info->data_len = len;
103395767ed7SCorey Minyard 	start_resend(ssif_info);
103495767ed7SCorey Minyard 	return 0;
103525930707SCorey Minyard }
103625930707SCorey Minyard 
103725930707SCorey Minyard /* Must be called with the message lock held. */
start_next_msg(struct ssif_info * ssif_info,unsigned long * flags)103825930707SCorey Minyard static void start_next_msg(struct ssif_info *ssif_info, unsigned long *flags)
103925930707SCorey Minyard {
104025930707SCorey Minyard 	struct ipmi_smi_msg *msg;
104125930707SCorey Minyard 	unsigned long oflags;
104225930707SCorey Minyard 
104325930707SCorey Minyard  restart:
10448230831cSCorey Minyard 	if (!IS_SSIF_IDLE(ssif_info)) {
104525930707SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
104625930707SCorey Minyard 		return;
104725930707SCorey Minyard 	}
104825930707SCorey Minyard 
104925930707SCorey Minyard 	if (!ssif_info->waiting_msg) {
105025930707SCorey Minyard 		ssif_info->curr_msg = NULL;
105125930707SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
105225930707SCorey Minyard 	} else {
105325930707SCorey Minyard 		int rv;
105425930707SCorey Minyard 
105525930707SCorey Minyard 		ssif_info->curr_msg = ssif_info->waiting_msg;
105625930707SCorey Minyard 		ssif_info->waiting_msg = NULL;
105725930707SCorey Minyard 		ipmi_ssif_unlock_cond(ssif_info, flags);
105825930707SCorey Minyard 		rv = start_send(ssif_info,
105925930707SCorey Minyard 				ssif_info->curr_msg->data,
106025930707SCorey Minyard 				ssif_info->curr_msg->data_size);
106125930707SCorey Minyard 		if (rv) {
106225930707SCorey Minyard 			msg = ssif_info->curr_msg;
106325930707SCorey Minyard 			ssif_info->curr_msg = NULL;
106425930707SCorey Minyard 			return_hosed_msg(ssif_info, msg);
106525930707SCorey Minyard 			flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
106625930707SCorey Minyard 			goto restart;
106725930707SCorey Minyard 		}
106825930707SCorey Minyard 	}
106925930707SCorey Minyard }
107025930707SCorey Minyard 
sender(void * send_info,struct ipmi_smi_msg * msg)107125930707SCorey Minyard static void sender(void                *send_info,
107225930707SCorey Minyard 		   struct ipmi_smi_msg *msg)
107325930707SCorey Minyard {
10745396ccbdSYu Zhe 	struct ssif_info *ssif_info = send_info;
107525930707SCorey Minyard 	unsigned long oflags, *flags;
107625930707SCorey Minyard 
107725930707SCorey Minyard 	BUG_ON(ssif_info->waiting_msg);
107825930707SCorey Minyard 	ssif_info->waiting_msg = msg;
107925930707SCorey Minyard 
108025930707SCorey Minyard 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
108125930707SCorey Minyard 	start_next_msg(ssif_info, flags);
108225930707SCorey Minyard 
108325930707SCorey Minyard 	if (ssif_info->ssif_debug & SSIF_DEBUG_TIMING) {
1084526290aaSAmitoj Kaur Chawla 		struct timespec64 t;
108525930707SCorey Minyard 
1086526290aaSAmitoj Kaur Chawla 		ktime_get_real_ts64(&t);
108783af4194SCorey Minyard 		dev_dbg(&ssif_info->client->dev,
108883af4194SCorey Minyard 			"**Enqueue %02x %02x: %lld.%6.6ld\n",
10891421c935SCorey Minyard 			msg->data[0], msg->data[1],
1090526290aaSAmitoj Kaur Chawla 			(long long)t.tv_sec, (long)t.tv_nsec / NSEC_PER_USEC);
109125930707SCorey Minyard 	}
109225930707SCorey Minyard }
109325930707SCorey Minyard 
get_smi_info(void * send_info,struct ipmi_smi_info * data)109425930707SCorey Minyard static int get_smi_info(void *send_info, struct ipmi_smi_info *data)
109525930707SCorey Minyard {
109625930707SCorey Minyard 	struct ssif_info *ssif_info = send_info;
109725930707SCorey Minyard 
109825930707SCorey Minyard 	data->addr_src = ssif_info->addr_source;
109925930707SCorey Minyard 	data->dev = &ssif_info->client->dev;
110025930707SCorey Minyard 	data->addr_info = ssif_info->addr_info;
110125930707SCorey Minyard 	get_device(data->dev);
110225930707SCorey Minyard 
110325930707SCorey Minyard 	return 0;
110425930707SCorey Minyard }
110525930707SCorey Minyard 
110625930707SCorey Minyard /*
1107a1466ec5SCorey Minyard  * Upper layer wants us to request events.
110825930707SCorey Minyard  */
request_events(void * send_info)110925930707SCorey Minyard static void request_events(void *send_info)
111025930707SCorey Minyard {
11115396ccbdSYu Zhe 	struct ssif_info *ssif_info = send_info;
111225930707SCorey Minyard 	unsigned long oflags, *flags;
111325930707SCorey Minyard 
111425930707SCorey Minyard 	if (!ssif_info->has_event_buffer)
111525930707SCorey Minyard 		return;
111625930707SCorey Minyard 
111725930707SCorey Minyard 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
111825930707SCorey Minyard 	ssif_info->req_events = true;
111925930707SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
112025930707SCorey Minyard }
1121a1466ec5SCorey Minyard 
1122a1466ec5SCorey Minyard /*
1123a1466ec5SCorey Minyard  * Upper layer is changing the flag saying whether we need to request
1124a1466ec5SCorey Minyard  * flags periodically or not.
1125a1466ec5SCorey Minyard  */
ssif_set_need_watch(void * send_info,unsigned int watch_mask)1126c65ea996SCorey Minyard static void ssif_set_need_watch(void *send_info, unsigned int watch_mask)
1127a1466ec5SCorey Minyard {
11285396ccbdSYu Zhe 	struct ssif_info *ssif_info = send_info;
1129a1466ec5SCorey Minyard 	unsigned long oflags, *flags;
1130c65ea996SCorey Minyard 	long timeout = 0;
1131c65ea996SCorey Minyard 
1132c65ea996SCorey Minyard 	if (watch_mask & IPMI_WATCH_MASK_CHECK_MESSAGES)
1133c65ea996SCorey Minyard 		timeout = SSIF_WATCH_MSG_TIMEOUT;
1134e1891cffSCorey Minyard 	else if (watch_mask)
1135c65ea996SCorey Minyard 		timeout = SSIF_WATCH_WATCHDOG_TIMEOUT;
1136a1466ec5SCorey Minyard 
1137a1466ec5SCorey Minyard 	flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
1138c65ea996SCorey Minyard 	if (timeout != ssif_info->watch_timeout) {
1139c65ea996SCorey Minyard 		ssif_info->watch_timeout = timeout;
1140c65ea996SCorey Minyard 		if (ssif_info->watch_timeout)
1141a1466ec5SCorey Minyard 			mod_timer(&ssif_info->watch_timer,
1142c65ea996SCorey Minyard 				  jiffies + ssif_info->watch_timeout);
1143a1466ec5SCorey Minyard 	}
1144a1466ec5SCorey Minyard 	ipmi_ssif_unlock_cond(ssif_info, flags);
114525930707SCorey Minyard }
114625930707SCorey Minyard 
ssif_start_processing(void * send_info,struct ipmi_smi * intf)114725930707SCorey Minyard static int ssif_start_processing(void            *send_info,
1148a567b623SCorey Minyard 				 struct ipmi_smi *intf)
114925930707SCorey Minyard {
115025930707SCorey Minyard 	struct ssif_info *ssif_info = send_info;
115125930707SCorey Minyard 
115225930707SCorey Minyard 	ssif_info->intf = intf;
115325930707SCorey Minyard 
115425930707SCorey Minyard 	return 0;
115525930707SCorey Minyard }
115625930707SCorey Minyard 
115725930707SCorey Minyard #define MAX_SSIF_BMCS 4
115825930707SCorey Minyard 
115925930707SCorey Minyard static unsigned short addr[MAX_SSIF_BMCS];
116025930707SCorey Minyard static int num_addrs;
116125930707SCorey Minyard module_param_array(addr, ushort, &num_addrs, 0);
116225930707SCorey Minyard MODULE_PARM_DESC(addr, "The addresses to scan for IPMI BMCs on the SSIFs.");
116325930707SCorey Minyard 
116425930707SCorey Minyard static char *adapter_name[MAX_SSIF_BMCS];
116525930707SCorey Minyard static int num_adapter_names;
116625930707SCorey Minyard module_param_array(adapter_name, charp, &num_adapter_names, 0);
116725930707SCorey Minyard MODULE_PARM_DESC(adapter_name, "The string name of the I2C device that has the BMC.  By default all devices are scanned.");
116825930707SCorey Minyard 
116925930707SCorey Minyard static int slave_addrs[MAX_SSIF_BMCS];
117025930707SCorey Minyard static int num_slave_addrs;
117125930707SCorey Minyard module_param_array(slave_addrs, int, &num_slave_addrs, 0);
117225930707SCorey Minyard MODULE_PARM_DESC(slave_addrs,
117325930707SCorey Minyard 		 "The default IPMB slave address for the controller.");
117425930707SCorey Minyard 
1175bf2d0877SCorey Minyard static bool alerts_broken;
1176bf2d0877SCorey Minyard module_param(alerts_broken, bool, 0);
1177bf2d0877SCorey Minyard MODULE_PARM_DESC(alerts_broken, "Don't enable alerts for the controller.");
1178bf2d0877SCorey Minyard 
117925930707SCorey Minyard /*
118025930707SCorey Minyard  * Bit 0 enables message debugging, bit 1 enables state debugging, and
118125930707SCorey Minyard  * bit 2 enables timing debugging.  This is an array indexed by
118225930707SCorey Minyard  * interface number"
118325930707SCorey Minyard  */
118425930707SCorey Minyard static int dbg[MAX_SSIF_BMCS];
118525930707SCorey Minyard static int num_dbg;
118625930707SCorey Minyard module_param_array(dbg, int, &num_dbg, 0);
118725930707SCorey Minyard MODULE_PARM_DESC(dbg, "Turn on debugging.");
118825930707SCorey Minyard 
118925930707SCorey Minyard static bool ssif_dbg_probe;
119025930707SCorey Minyard module_param_named(dbg_probe, ssif_dbg_probe, bool, 0);
119125930707SCorey Minyard MODULE_PARM_DESC(dbg_probe, "Enable debugging of probing of adapters.");
119225930707SCorey Minyard 
1193fedb25eaSShailendra Verma static bool ssif_tryacpi = true;
119425930707SCorey Minyard module_param_named(tryacpi, ssif_tryacpi, bool, 0);
119525930707SCorey Minyard MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the default scan of the interfaces identified via ACPI");
119625930707SCorey Minyard 
1197fedb25eaSShailendra Verma static bool ssif_trydmi = true;
119825930707SCorey Minyard module_param_named(trydmi, ssif_trydmi, bool, 0);
119925930707SCorey Minyard MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the default scan of the interfaces identified via DMI (SMBIOS)");
120025930707SCorey Minyard 
120125930707SCorey Minyard static DEFINE_MUTEX(ssif_infos_mutex);
120225930707SCorey Minyard static LIST_HEAD(ssif_infos);
120325930707SCorey Minyard 
1204ac2673d5SCorey Minyard #define IPMI_SSIF_ATTR(name) \
1205ac2673d5SCorey Minyard static ssize_t ipmi_##name##_show(struct device *dev,			\
1206ac2673d5SCorey Minyard 				  struct device_attribute *attr,	\
1207ac2673d5SCorey Minyard 				  char *buf)				\
1208ac2673d5SCorey Minyard {									\
1209ac2673d5SCorey Minyard 	struct ssif_info *ssif_info = dev_get_drvdata(dev);		\
1210ac2673d5SCorey Minyard 									\
1211fc4e7848SYe Guojin 	return sysfs_emit(buf, "%u\n", ssif_get_stat(ssif_info, name));\
1212ac2673d5SCorey Minyard }									\
1213ac2673d5SCorey Minyard static DEVICE_ATTR(name, S_IRUGO, ipmi_##name##_show, NULL)
1214ac2673d5SCorey Minyard 
ipmi_type_show(struct device * dev,struct device_attribute * attr,char * buf)1215ac2673d5SCorey Minyard static ssize_t ipmi_type_show(struct device *dev,
1216ac2673d5SCorey Minyard 			      struct device_attribute *attr,
1217ac2673d5SCorey Minyard 			      char *buf)
1218ac2673d5SCorey Minyard {
1219fc4e7848SYe Guojin 	return sysfs_emit(buf, "ssif\n");
1220ac2673d5SCorey Minyard }
1221ac2673d5SCorey Minyard static DEVICE_ATTR(type, S_IRUGO, ipmi_type_show, NULL);
1222ac2673d5SCorey Minyard 
1223ac2673d5SCorey Minyard IPMI_SSIF_ATTR(sent_messages);
1224ac2673d5SCorey Minyard IPMI_SSIF_ATTR(sent_messages_parts);
1225ac2673d5SCorey Minyard IPMI_SSIF_ATTR(send_retries);
1226ac2673d5SCorey Minyard IPMI_SSIF_ATTR(send_errors);
1227ac2673d5SCorey Minyard IPMI_SSIF_ATTR(received_messages);
1228ac2673d5SCorey Minyard IPMI_SSIF_ATTR(received_message_parts);
1229ac2673d5SCorey Minyard IPMI_SSIF_ATTR(receive_retries);
1230ac2673d5SCorey Minyard IPMI_SSIF_ATTR(receive_errors);
1231ac2673d5SCorey Minyard IPMI_SSIF_ATTR(flag_fetches);
1232ac2673d5SCorey Minyard IPMI_SSIF_ATTR(hosed);
1233ac2673d5SCorey Minyard IPMI_SSIF_ATTR(events);
1234ac2673d5SCorey Minyard IPMI_SSIF_ATTR(watchdog_pretimeouts);
1235ac2673d5SCorey Minyard IPMI_SSIF_ATTR(alerts);
1236ac2673d5SCorey Minyard 
1237ac2673d5SCorey Minyard static struct attribute *ipmi_ssif_dev_attrs[] = {
1238ac2673d5SCorey Minyard 	&dev_attr_type.attr,
1239ac2673d5SCorey Minyard 	&dev_attr_sent_messages.attr,
1240ac2673d5SCorey Minyard 	&dev_attr_sent_messages_parts.attr,
1241ac2673d5SCorey Minyard 	&dev_attr_send_retries.attr,
1242ac2673d5SCorey Minyard 	&dev_attr_send_errors.attr,
1243ac2673d5SCorey Minyard 	&dev_attr_received_messages.attr,
1244ac2673d5SCorey Minyard 	&dev_attr_received_message_parts.attr,
1245ac2673d5SCorey Minyard 	&dev_attr_receive_retries.attr,
1246ac2673d5SCorey Minyard 	&dev_attr_receive_errors.attr,
1247ac2673d5SCorey Minyard 	&dev_attr_flag_fetches.attr,
1248ac2673d5SCorey Minyard 	&dev_attr_hosed.attr,
1249ac2673d5SCorey Minyard 	&dev_attr_events.attr,
1250ac2673d5SCorey Minyard 	&dev_attr_watchdog_pretimeouts.attr,
1251ac2673d5SCorey Minyard 	&dev_attr_alerts.attr,
1252ac2673d5SCorey Minyard 	NULL
1253ac2673d5SCorey Minyard };
1254ac2673d5SCorey Minyard 
1255ac2673d5SCorey Minyard static const struct attribute_group ipmi_ssif_dev_attr_group = {
1256ac2673d5SCorey Minyard 	.attrs		= ipmi_ssif_dev_attrs,
1257ac2673d5SCorey Minyard };
1258ac2673d5SCorey Minyard 
shutdown_ssif(void * send_info)1259a313dec6SCorey Minyard static void shutdown_ssif(void *send_info)
126025930707SCorey Minyard {
1261a313dec6SCorey Minyard 	struct ssif_info *ssif_info = send_info;
126225930707SCorey Minyard 
1263ac2673d5SCorey Minyard 	device_remove_group(&ssif_info->client->dev, &ipmi_ssif_dev_attr_group);
1264ac2673d5SCorey Minyard 	dev_set_drvdata(&ssif_info->client->dev, NULL);
1265ac2673d5SCorey Minyard 
126625930707SCorey Minyard 	/* make sure the driver is not looking for flags any more. */
12678230831cSCorey Minyard 	while (ssif_info->ssif_state != SSIF_IDLE)
126825930707SCorey Minyard 		schedule_timeout(1);
126925930707SCorey Minyard 
127025930707SCorey Minyard 	ssif_info->stopping = true;
1271a1466ec5SCorey Minyard 	del_timer_sync(&ssif_info->watch_timer);
127225930707SCorey Minyard 	del_timer_sync(&ssif_info->retry_timer);
127325930707SCorey Minyard 	if (ssif_info->thread) {
127425930707SCorey Minyard 		complete(&ssif_info->wake_thread);
127525930707SCorey Minyard 		kthread_stop(ssif_info->thread);
127625930707SCorey Minyard 	}
1277a313dec6SCorey Minyard }
1278a313dec6SCorey Minyard 
ssif_remove(struct i2c_client * client)1279ed5c2f5fSUwe Kleine-König static void ssif_remove(struct i2c_client *client)
1280a313dec6SCorey Minyard {
1281a313dec6SCorey Minyard 	struct ssif_info *ssif_info = i2c_get_clientdata(client);
1282a313dec6SCorey Minyard 	struct ssif_addr_info *addr_info;
1283a313dec6SCorey Minyard 
1284a313dec6SCorey Minyard 	/*
1285957c822aSzipeng zhang 	 * After this point, we won't deliver anything asynchronously
1286a313dec6SCorey Minyard 	 * to the message handler.  We can unregister ourself.
1287a313dec6SCorey Minyard 	 */
12882512e40eSCorey Minyard 	ipmi_unregister_smi(ssif_info->intf);
1289a313dec6SCorey Minyard 
12900944d889SCorey Minyard 	list_for_each_entry(addr_info, &ssif_infos, link) {
12910944d889SCorey Minyard 		if (addr_info->client == client) {
12920944d889SCorey Minyard 			addr_info->client = NULL;
12930944d889SCorey Minyard 			break;
12940944d889SCorey Minyard 		}
12950944d889SCorey Minyard 	}
12960944d889SCorey Minyard 
12972512e40eSCorey Minyard 	kfree(ssif_info);
129825930707SCorey Minyard }
129925930707SCorey Minyard 
read_response(struct i2c_client * client,unsigned char * resp)130010042504SCorey Minyard static int read_response(struct i2c_client *client, unsigned char *resp)
130110042504SCorey Minyard {
130210042504SCorey Minyard 	int ret = -ENODEV, retry_cnt = SSIF_RECV_RETRIES;
130310042504SCorey Minyard 
130410042504SCorey Minyard 	while (retry_cnt > 0) {
130510042504SCorey Minyard 		ret = i2c_smbus_read_block_data(client, SSIF_IPMI_RESPONSE,
130610042504SCorey Minyard 						resp);
130710042504SCorey Minyard 		if (ret > 0)
130810042504SCorey Minyard 			break;
130910042504SCorey Minyard 		msleep(SSIF_MSG_MSEC);
131010042504SCorey Minyard 		retry_cnt--;
131110042504SCorey Minyard 		if (retry_cnt <= 0)
131210042504SCorey Minyard 			break;
131310042504SCorey Minyard 	}
131410042504SCorey Minyard 
131510042504SCorey Minyard 	return ret;
131610042504SCorey Minyard }
131710042504SCorey Minyard 
do_cmd(struct i2c_client * client,int len,unsigned char * msg,int * resp_len,unsigned char * resp)131825930707SCorey Minyard static int do_cmd(struct i2c_client *client, int len, unsigned char *msg,
131925930707SCorey Minyard 		  int *resp_len, unsigned char *resp)
132025930707SCorey Minyard {
132125930707SCorey Minyard 	int retry_cnt;
132225930707SCorey Minyard 	int ret;
132325930707SCorey Minyard 
132425930707SCorey Minyard 	retry_cnt = SSIF_SEND_RETRIES;
132525930707SCorey Minyard  retry1:
132625930707SCorey Minyard 	ret = i2c_smbus_write_block_data(client, SSIF_IPMI_REQUEST, len, msg);
132725930707SCorey Minyard 	if (ret) {
132825930707SCorey Minyard 		retry_cnt--;
132900bb7e76SCorey Minyard 		if (retry_cnt > 0) {
133000bb7e76SCorey Minyard 			msleep(SSIF_REQ_RETRY_MSEC);
133125930707SCorey Minyard 			goto retry1;
133200bb7e76SCorey Minyard 		}
133325930707SCorey Minyard 		return -ENODEV;
133425930707SCorey Minyard 	}
133525930707SCorey Minyard 
133610042504SCorey Minyard 	ret = read_response(client, resp);
133725930707SCorey Minyard 	if (ret > 0) {
133825930707SCorey Minyard 		/* Validate that the response is correct. */
133925930707SCorey Minyard 		if (ret < 3 ||
134025930707SCorey Minyard 		    (resp[0] != (msg[0] | (1 << 2))) ||
134125930707SCorey Minyard 		    (resp[1] != msg[1]))
134225930707SCorey Minyard 			ret = -EINVAL;
134310042504SCorey Minyard 		else if (ret > IPMI_MAX_MSG_LENGTH) {
134410042504SCorey Minyard 			ret = -E2BIG;
134510042504SCorey Minyard 		} else {
134625930707SCorey Minyard 			*resp_len = ret;
134725930707SCorey Minyard 			ret = 0;
134825930707SCorey Minyard 		}
134925930707SCorey Minyard 	}
135025930707SCorey Minyard 
135125930707SCorey Minyard 	return ret;
135225930707SCorey Minyard }
135325930707SCorey Minyard 
ssif_detect(struct i2c_client * client,struct i2c_board_info * info)135425930707SCorey Minyard static int ssif_detect(struct i2c_client *client, struct i2c_board_info *info)
135525930707SCorey Minyard {
135625930707SCorey Minyard 	unsigned char *resp;
135725930707SCorey Minyard 	unsigned char msg[3];
135825930707SCorey Minyard 	int           rv;
135925930707SCorey Minyard 	int           len;
136025930707SCorey Minyard 
136125930707SCorey Minyard 	resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
136225930707SCorey Minyard 	if (!resp)
136325930707SCorey Minyard 		return -ENOMEM;
136425930707SCorey Minyard 
136525930707SCorey Minyard 	/* Do a Get Device ID command, since it is required. */
136625930707SCorey Minyard 	msg[0] = IPMI_NETFN_APP_REQUEST << 2;
136725930707SCorey Minyard 	msg[1] = IPMI_GET_DEVICE_ID_CMD;
136825930707SCorey Minyard 	rv = do_cmd(client, 2, msg, &len, resp);
136925930707SCorey Minyard 	if (rv)
137025930707SCorey Minyard 		rv = -ENODEV;
137125930707SCorey Minyard 	else
1372d134ad25SJason Wang 		strscpy(info->type, DEVICE_NAME, I2C_NAME_SIZE);
137325930707SCorey Minyard 	kfree(resp);
137425930707SCorey Minyard 	return rv;
137525930707SCorey Minyard }
137625930707SCorey Minyard 
strcmp_nospace(char * s1,char * s2)1377b0e9aaa9SCorey Minyard static int strcmp_nospace(char *s1, char *s2)
1378b0e9aaa9SCorey Minyard {
1379b0e9aaa9SCorey Minyard 	while (*s1 && *s2) {
1380b0e9aaa9SCorey Minyard 		while (isspace(*s1))
1381b0e9aaa9SCorey Minyard 			s1++;
1382b0e9aaa9SCorey Minyard 		while (isspace(*s2))
1383b0e9aaa9SCorey Minyard 			s2++;
1384b0e9aaa9SCorey Minyard 		if (*s1 > *s2)
1385b0e9aaa9SCorey Minyard 			return 1;
1386b0e9aaa9SCorey Minyard 		if (*s1 < *s2)
1387b0e9aaa9SCorey Minyard 			return -1;
1388b0e9aaa9SCorey Minyard 		s1++;
1389b0e9aaa9SCorey Minyard 		s2++;
1390b0e9aaa9SCorey Minyard 	}
1391b0e9aaa9SCorey Minyard 	return 0;
1392b0e9aaa9SCorey Minyard }
1393b0e9aaa9SCorey Minyard 
ssif_info_find(unsigned short addr,char * adapter_name,bool match_null_name)139425930707SCorey Minyard static struct ssif_addr_info *ssif_info_find(unsigned short addr,
139525930707SCorey Minyard 					     char *adapter_name,
139625930707SCorey Minyard 					     bool match_null_name)
139725930707SCorey Minyard {
139825930707SCorey Minyard 	struct ssif_addr_info *info, *found = NULL;
139925930707SCorey Minyard 
140025930707SCorey Minyard restart:
140125930707SCorey Minyard 	list_for_each_entry(info, &ssif_infos, link) {
140225930707SCorey Minyard 		if (info->binfo.addr == addr) {
1403b8d72e32SCorey Minyard 			if (info->addr_src == SI_SMBIOS && !info->adapter_name)
1404c4436c91SKamlakant Patel 				info->adapter_name = kstrdup(adapter_name,
1405c4436c91SKamlakant Patel 							     GFP_KERNEL);
1406c4436c91SKamlakant Patel 
140725930707SCorey Minyard 			if (info->adapter_name || adapter_name) {
140825930707SCorey Minyard 				if (!info->adapter_name != !adapter_name) {
140925930707SCorey Minyard 					/* One is NULL and one is not */
141025930707SCorey Minyard 					continue;
141125930707SCorey Minyard 				}
1412b0e9aaa9SCorey Minyard 				if (adapter_name &&
1413b0e9aaa9SCorey Minyard 				    strcmp_nospace(info->adapter_name,
1414b0e9aaa9SCorey Minyard 						   adapter_name))
1415b0e9aaa9SCorey Minyard 					/* Names do not match */
141625930707SCorey Minyard 					continue;
141725930707SCorey Minyard 			}
141825930707SCorey Minyard 			found = info;
141925930707SCorey Minyard 			break;
142025930707SCorey Minyard 		}
142125930707SCorey Minyard 	}
142225930707SCorey Minyard 
142325930707SCorey Minyard 	if (!found && match_null_name) {
142425930707SCorey Minyard 		/* Try to get an exact match first, then try with a NULL name */
142525930707SCorey Minyard 		adapter_name = NULL;
142625930707SCorey Minyard 		match_null_name = false;
142725930707SCorey Minyard 		goto restart;
142825930707SCorey Minyard 	}
142925930707SCorey Minyard 
143025930707SCorey Minyard 	return found;
143125930707SCorey Minyard }
143225930707SCorey Minyard 
check_acpi(struct ssif_info * ssif_info,struct device * dev)143325930707SCorey Minyard static bool check_acpi(struct ssif_info *ssif_info, struct device *dev)
143425930707SCorey Minyard {
143525930707SCorey Minyard #ifdef CONFIG_ACPI
143625930707SCorey Minyard 	acpi_handle acpi_handle;
143725930707SCorey Minyard 
143825930707SCorey Minyard 	acpi_handle = ACPI_HANDLE(dev);
143925930707SCorey Minyard 	if (acpi_handle) {
144025930707SCorey Minyard 		ssif_info->addr_source = SI_ACPI;
144125930707SCorey Minyard 		ssif_info->addr_info.acpi_info.acpi_handle = acpi_handle;
1442*e87443a5SCorey Minyard 		request_module_nowait("acpi_ipmi");
144325930707SCorey Minyard 		return true;
144425930707SCorey Minyard 	}
144525930707SCorey Minyard #endif
144625930707SCorey Minyard 	return false;
144725930707SCorey Minyard }
144825930707SCorey Minyard 
find_slave_address(struct i2c_client * client,int slave_addr)144994671710SCorey Minyard static int find_slave_address(struct i2c_client *client, int slave_addr)
145094671710SCorey Minyard {
14510944d889SCorey Minyard #ifdef CONFIG_IPMI_DMI_DECODE
14520944d889SCorey Minyard 	if (!slave_addr)
14530944d889SCorey Minyard 		slave_addr = ipmi_dmi_get_slave_addr(
145495e300c0SCorey Minyard 			SI_TYPE_INVALID,
14550944d889SCorey Minyard 			i2c_adapter_id(client->adapter),
14560944d889SCorey Minyard 			client->addr);
14570944d889SCorey Minyard #endif
145894671710SCorey Minyard 
145994671710SCorey Minyard 	return slave_addr;
146094671710SCorey Minyard }
146194671710SCorey Minyard 
start_multipart_test(struct i2c_client * client,unsigned char * msg,bool do_middle)146210042504SCorey Minyard static int start_multipart_test(struct i2c_client *client,
146310042504SCorey Minyard 				unsigned char *msg, bool do_middle)
146410042504SCorey Minyard {
146510042504SCorey Minyard 	int retry_cnt = SSIF_SEND_RETRIES, ret;
146610042504SCorey Minyard 
146710042504SCorey Minyard retry_write:
146810042504SCorey Minyard 	ret = i2c_smbus_write_block_data(client,
146910042504SCorey Minyard 					 SSIF_IPMI_MULTI_PART_REQUEST_START,
147010042504SCorey Minyard 					 32, msg);
147110042504SCorey Minyard 	if (ret) {
147210042504SCorey Minyard 		retry_cnt--;
147300bb7e76SCorey Minyard 		if (retry_cnt > 0) {
147400bb7e76SCorey Minyard 			msleep(SSIF_REQ_RETRY_MSEC);
147510042504SCorey Minyard 			goto retry_write;
147600bb7e76SCorey Minyard 		}
147710042504SCorey Minyard 		dev_err(&client->dev, "Could not write multi-part start, though the BMC said it could handle it.  Just limit sends to one part.\n");
147810042504SCorey Minyard 		return ret;
147910042504SCorey Minyard 	}
148010042504SCorey Minyard 
148110042504SCorey Minyard 	if (!do_middle)
148210042504SCorey Minyard 		return 0;
148310042504SCorey Minyard 
148410042504SCorey Minyard 	ret = i2c_smbus_write_block_data(client,
148510042504SCorey Minyard 					 SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE,
148610042504SCorey Minyard 					 32, msg + 32);
148710042504SCorey Minyard 	if (ret) {
148810042504SCorey Minyard 		dev_err(&client->dev, "Could not write multi-part middle, though the BMC said it could handle it.  Just limit sends to one part.\n");
148910042504SCorey Minyard 		return ret;
149010042504SCorey Minyard 	}
149110042504SCorey Minyard 
149210042504SCorey Minyard 	return 0;
149310042504SCorey Minyard }
149410042504SCorey Minyard 
test_multipart_messages(struct i2c_client * client,struct ssif_info * ssif_info,unsigned char * resp)149510042504SCorey Minyard static void test_multipart_messages(struct i2c_client *client,
149610042504SCorey Minyard 				    struct ssif_info *ssif_info,
149710042504SCorey Minyard 				    unsigned char *resp)
149810042504SCorey Minyard {
149910042504SCorey Minyard 	unsigned char msg[65];
150010042504SCorey Minyard 	int ret;
150110042504SCorey Minyard 	bool do_middle;
150210042504SCorey Minyard 
150310042504SCorey Minyard 	if (ssif_info->max_xmit_msg_size <= 32)
150410042504SCorey Minyard 		return;
150510042504SCorey Minyard 
150610042504SCorey Minyard 	do_middle = ssif_info->max_xmit_msg_size > 63;
150710042504SCorey Minyard 
150810042504SCorey Minyard 	memset(msg, 0, sizeof(msg));
150910042504SCorey Minyard 	msg[0] = IPMI_NETFN_APP_REQUEST << 2;
151010042504SCorey Minyard 	msg[1] = IPMI_GET_DEVICE_ID_CMD;
151110042504SCorey Minyard 
151210042504SCorey Minyard 	/*
151310042504SCorey Minyard 	 * The specification is all messed up dealing with sending
151410042504SCorey Minyard 	 * multi-part messages.  Per what the specification says, it
151510042504SCorey Minyard 	 * is impossible to send a message that is a multiple of 32
151610042504SCorey Minyard 	 * bytes, except for 32 itself.  It talks about a "start"
151710042504SCorey Minyard 	 * transaction (cmd=6) that must be 32 bytes, "middle"
151810042504SCorey Minyard 	 * transaction (cmd=7) that must be 32 bytes, and an "end"
151910042504SCorey Minyard 	 * transaction.  The "end" transaction is shown as cmd=7 in
152010042504SCorey Minyard 	 * the text, but if that's the case there is no way to
152110042504SCorey Minyard 	 * differentiate between a middle and end part except the
152210042504SCorey Minyard 	 * length being less than 32.  But there is a table at the far
152310042504SCorey Minyard 	 * end of the section (that I had never noticed until someone
152410042504SCorey Minyard 	 * pointed it out to me) that mentions it as cmd=8.
152510042504SCorey Minyard 	 *
152610042504SCorey Minyard 	 * After some thought, I think the example is wrong and the
152710042504SCorey Minyard 	 * end transaction should be cmd=8.  But some systems don't
152810042504SCorey Minyard 	 * implement cmd=8, they use a zero-length end transaction,
152910042504SCorey Minyard 	 * even though that violates the SMBus specification.
153010042504SCorey Minyard 	 *
153110042504SCorey Minyard 	 * So, to work around this, this code tests if cmd=8 works.
153210042504SCorey Minyard 	 * If it does, then we use that.  If not, it tests zero-
153310042504SCorey Minyard 	 * byte end transactions.  If that works, good.  If not,
153410042504SCorey Minyard 	 * we only allow 63-byte transactions max.
153510042504SCorey Minyard 	 */
153610042504SCorey Minyard 
153710042504SCorey Minyard 	ret = start_multipart_test(client, msg, do_middle);
153810042504SCorey Minyard 	if (ret)
153910042504SCorey Minyard 		goto out_no_multi_part;
154010042504SCorey Minyard 
154110042504SCorey Minyard 	ret = i2c_smbus_write_block_data(client,
154210042504SCorey Minyard 					 SSIF_IPMI_MULTI_PART_REQUEST_END,
154310042504SCorey Minyard 					 1, msg + 64);
154410042504SCorey Minyard 
154510042504SCorey Minyard 	if (!ret)
154610042504SCorey Minyard 		ret = read_response(client, resp);
154710042504SCorey Minyard 
154810042504SCorey Minyard 	if (ret > 0) {
154910042504SCorey Minyard 		/* End transactions work, we are good. */
155010042504SCorey Minyard 		ssif_info->cmd8_works = true;
155110042504SCorey Minyard 		return;
155210042504SCorey Minyard 	}
155310042504SCorey Minyard 
155410042504SCorey Minyard 	ret = start_multipart_test(client, msg, do_middle);
155510042504SCorey Minyard 	if (ret) {
155610042504SCorey Minyard 		dev_err(&client->dev, "Second multipart test failed.\n");
155710042504SCorey Minyard 		goto out_no_multi_part;
155810042504SCorey Minyard 	}
155910042504SCorey Minyard 
156010042504SCorey Minyard 	ret = i2c_smbus_write_block_data(client,
156110042504SCorey Minyard 					 SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE,
156210042504SCorey Minyard 					 0, msg + 64);
156310042504SCorey Minyard 	if (!ret)
156410042504SCorey Minyard 		ret = read_response(client, resp);
156510042504SCorey Minyard 	if (ret > 0)
156610042504SCorey Minyard 		/* Zero-size end parts work, use those. */
156710042504SCorey Minyard 		return;
156810042504SCorey Minyard 
156910042504SCorey Minyard 	/* Limit to 63 bytes and use a short middle command to mark the end. */
157010042504SCorey Minyard 	if (ssif_info->max_xmit_msg_size > 63)
157110042504SCorey Minyard 		ssif_info->max_xmit_msg_size = 63;
157210042504SCorey Minyard 	return;
157310042504SCorey Minyard 
157410042504SCorey Minyard out_no_multi_part:
157510042504SCorey Minyard 	ssif_info->max_xmit_msg_size = 32;
157610042504SCorey Minyard 	return;
157710042504SCorey Minyard }
157810042504SCorey Minyard 
157991620521SCorey Minyard /*
158091620521SCorey Minyard  * Global enables we care about.
158191620521SCorey Minyard  */
158291620521SCorey Minyard #define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR | \
158391620521SCorey Minyard 			     IPMI_BMC_EVT_MSG_INTR)
158491620521SCorey Minyard 
ssif_remove_dup(struct i2c_client * client)1585c4436c91SKamlakant Patel static void ssif_remove_dup(struct i2c_client *client)
1586c4436c91SKamlakant Patel {
1587c4436c91SKamlakant Patel 	struct ssif_info *ssif_info = i2c_get_clientdata(client);
1588c4436c91SKamlakant Patel 
1589c4436c91SKamlakant Patel 	ipmi_unregister_smi(ssif_info->intf);
1590c4436c91SKamlakant Patel 	kfree(ssif_info);
1591c4436c91SKamlakant Patel }
1592c4436c91SKamlakant Patel 
ssif_add_infos(struct i2c_client * client)1593c4436c91SKamlakant Patel static int ssif_add_infos(struct i2c_client *client)
1594c4436c91SKamlakant Patel {
1595c4436c91SKamlakant Patel 	struct ssif_addr_info *info;
1596c4436c91SKamlakant Patel 
1597c4436c91SKamlakant Patel 	info = kzalloc(sizeof(*info), GFP_KERNEL);
1598c4436c91SKamlakant Patel 	if (!info)
1599c4436c91SKamlakant Patel 		return -ENOMEM;
1600c4436c91SKamlakant Patel 	info->addr_src = SI_ACPI;
1601c4436c91SKamlakant Patel 	info->client = client;
1602c4436c91SKamlakant Patel 	info->adapter_name = kstrdup(client->adapter->name, GFP_KERNEL);
1603c5586d0fSJiasheng Jiang 	if (!info->adapter_name) {
1604c5586d0fSJiasheng Jiang 		kfree(info);
1605c5586d0fSJiasheng Jiang 		return -ENOMEM;
1606c5586d0fSJiasheng Jiang 	}
1607c5586d0fSJiasheng Jiang 
1608c4436c91SKamlakant Patel 	info->binfo.addr = client->addr;
1609c4436c91SKamlakant Patel 	list_add_tail(&info->link, &ssif_infos);
1610c4436c91SKamlakant Patel 	return 0;
1611c4436c91SKamlakant Patel }
1612c4436c91SKamlakant Patel 
1613c4436c91SKamlakant Patel /*
1614c4436c91SKamlakant Patel  * Prefer ACPI over SMBIOS, if both are available.
1615c4436c91SKamlakant Patel  * So if we get an ACPI interface and have already registered a SMBIOS
1616c4436c91SKamlakant Patel  * interface at the same address, remove the SMBIOS and add the ACPI one.
1617c4436c91SKamlakant Patel  */
ssif_check_and_remove(struct i2c_client * client,struct ssif_info * ssif_info)1618c4436c91SKamlakant Patel static int ssif_check_and_remove(struct i2c_client *client,
1619c4436c91SKamlakant Patel 			      struct ssif_info *ssif_info)
1620c4436c91SKamlakant Patel {
1621c4436c91SKamlakant Patel 	struct ssif_addr_info *info;
1622c4436c91SKamlakant Patel 
1623c4436c91SKamlakant Patel 	list_for_each_entry(info, &ssif_infos, link) {
1624c4436c91SKamlakant Patel 		if (!info->client)
1625c4436c91SKamlakant Patel 			return 0;
1626c4436c91SKamlakant Patel 		if (!strcmp(info->adapter_name, client->adapter->name) &&
1627c4436c91SKamlakant Patel 		    info->binfo.addr == client->addr) {
1628c4436c91SKamlakant Patel 			if (info->addr_src == SI_ACPI)
1629c4436c91SKamlakant Patel 				return -EEXIST;
1630c4436c91SKamlakant Patel 
1631c4436c91SKamlakant Patel 			if (ssif_info->addr_source == SI_ACPI &&
1632c4436c91SKamlakant Patel 			    info->addr_src == SI_SMBIOS) {
1633c4436c91SKamlakant Patel 				dev_info(&client->dev,
1634c4436c91SKamlakant Patel 					 "Removing %s-specified SSIF interface in favor of ACPI\n",
1635c4436c91SKamlakant Patel 					 ipmi_addr_src_to_str(info->addr_src));
1636c4436c91SKamlakant Patel 				ssif_remove_dup(info->client);
1637c4436c91SKamlakant Patel 				return 0;
1638c4436c91SKamlakant Patel 			}
1639c4436c91SKamlakant Patel 		}
1640c4436c91SKamlakant Patel 	}
1641c4436c91SKamlakant Patel 	return 0;
1642c4436c91SKamlakant Patel }
1643c4436c91SKamlakant Patel 
ssif_probe(struct i2c_client * client)16440924c5a0SStephen Kitt static int ssif_probe(struct i2c_client *client)
164525930707SCorey Minyard {
164625930707SCorey Minyard 	unsigned char     msg[3];
164725930707SCorey Minyard 	unsigned char     *resp;
164825930707SCorey Minyard 	struct ssif_info   *ssif_info;
164925930707SCorey Minyard 	int               rv = 0;
16508d10ea15STom Rix 	int               len = 0;
165125930707SCorey Minyard 	int               i;
165225930707SCorey Minyard 	u8		  slave_addr = 0;
165325930707SCorey Minyard 	struct ssif_addr_info *addr_info = NULL;
165425930707SCorey Minyard 
1655c4436c91SKamlakant Patel 	mutex_lock(&ssif_infos_mutex);
165625930707SCorey Minyard 	resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
1657c4436c91SKamlakant Patel 	if (!resp) {
1658c4436c91SKamlakant Patel 		mutex_unlock(&ssif_infos_mutex);
165925930707SCorey Minyard 		return -ENOMEM;
1660c4436c91SKamlakant Patel 	}
166125930707SCorey Minyard 
166225930707SCorey Minyard 	ssif_info = kzalloc(sizeof(*ssif_info), GFP_KERNEL);
166325930707SCorey Minyard 	if (!ssif_info) {
166425930707SCorey Minyard 		kfree(resp);
1665c4436c91SKamlakant Patel 		mutex_unlock(&ssif_infos_mutex);
166625930707SCorey Minyard 		return -ENOMEM;
166725930707SCorey Minyard 	}
166825930707SCorey Minyard 
166925930707SCorey Minyard 	if (!check_acpi(ssif_info, &client->dev)) {
167025930707SCorey Minyard 		addr_info = ssif_info_find(client->addr, client->adapter->name,
167125930707SCorey Minyard 					   true);
167225930707SCorey Minyard 		if (!addr_info) {
167325930707SCorey Minyard 			/* Must have come in through sysfs. */
167425930707SCorey Minyard 			ssif_info->addr_source = SI_HOTMOD;
167525930707SCorey Minyard 		} else {
167625930707SCorey Minyard 			ssif_info->addr_source = addr_info->addr_src;
167725930707SCorey Minyard 			ssif_info->ssif_debug = addr_info->debug;
167825930707SCorey Minyard 			ssif_info->addr_info = addr_info->addr_info;
16790944d889SCorey Minyard 			addr_info->client = client;
168025930707SCorey Minyard 			slave_addr = addr_info->slave_addr;
168125930707SCorey Minyard 		}
168225930707SCorey Minyard 	}
168325930707SCorey Minyard 
168434f35f8fSMian Yousaf Kaukab 	ssif_info->client = client;
168534f35f8fSMian Yousaf Kaukab 	i2c_set_clientdata(client, ssif_info);
168634f35f8fSMian Yousaf Kaukab 
1687c4436c91SKamlakant Patel 	rv = ssif_check_and_remove(client, ssif_info);
1688c4436c91SKamlakant Patel 	/* If rv is 0 and addr source is not SI_ACPI, continue probing */
1689c4436c91SKamlakant Patel 	if (!rv && ssif_info->addr_source == SI_ACPI) {
1690c4436c91SKamlakant Patel 		rv = ssif_add_infos(client);
1691c4436c91SKamlakant Patel 		if (rv) {
1692c4436c91SKamlakant Patel 			dev_err(&client->dev, "Out of memory!, exiting ..\n");
1693c4436c91SKamlakant Patel 			goto out;
1694c4436c91SKamlakant Patel 		}
1695c4436c91SKamlakant Patel 	} else if (rv) {
1696c4436c91SKamlakant Patel 		dev_err(&client->dev, "Not probing, Interface already present\n");
1697c4436c91SKamlakant Patel 		goto out;
1698c4436c91SKamlakant Patel 	}
1699c4436c91SKamlakant Patel 
170094671710SCorey Minyard 	slave_addr = find_slave_address(client, slave_addr);
170194671710SCorey Minyard 
170283af4194SCorey Minyard 	dev_info(&client->dev,
170383af4194SCorey Minyard 		 "Trying %s-specified SSIF interface at i2c address 0x%x, adapter %s, slave address 0x%x\n",
170425930707SCorey Minyard 		ipmi_addr_src_to_str(ssif_info->addr_source),
170525930707SCorey Minyard 		client->addr, client->adapter->name, slave_addr);
170625930707SCorey Minyard 
170725930707SCorey Minyard 	/* Now check for system interface capabilities */
170825930707SCorey Minyard 	msg[0] = IPMI_NETFN_APP_REQUEST << 2;
170925930707SCorey Minyard 	msg[1] = IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD;
171025930707SCorey Minyard 	msg[2] = 0; /* SSIF */
171125930707SCorey Minyard 	rv = do_cmd(client, 3, msg, &len, resp);
171225930707SCorey Minyard 	if (!rv && (len >= 3) && (resp[2] == 0)) {
171325930707SCorey Minyard 		if (len < 7) {
171425930707SCorey Minyard 			if (ssif_dbg_probe)
171583af4194SCorey Minyard 				dev_dbg(&ssif_info->client->dev,
171683af4194SCorey Minyard 					"SSIF info too short: %d\n", len);
171725930707SCorey Minyard 			goto no_support;
171825930707SCorey Minyard 		}
171925930707SCorey Minyard 
172025930707SCorey Minyard 		/* Got a good SSIF response, handle it. */
172125930707SCorey Minyard 		ssif_info->max_xmit_msg_size = resp[5];
172225930707SCorey Minyard 		ssif_info->max_recv_msg_size = resp[6];
172325930707SCorey Minyard 		ssif_info->multi_support = (resp[4] >> 6) & 0x3;
172425930707SCorey Minyard 		ssif_info->supports_pec = (resp[4] >> 3) & 0x1;
172525930707SCorey Minyard 
172625930707SCorey Minyard 		/* Sanitize the data */
172725930707SCorey Minyard 		switch (ssif_info->multi_support) {
172825930707SCorey Minyard 		case SSIF_NO_MULTI:
172925930707SCorey Minyard 			if (ssif_info->max_xmit_msg_size > 32)
173025930707SCorey Minyard 				ssif_info->max_xmit_msg_size = 32;
173125930707SCorey Minyard 			if (ssif_info->max_recv_msg_size > 32)
173225930707SCorey Minyard 				ssif_info->max_recv_msg_size = 32;
173325930707SCorey Minyard 			break;
173425930707SCorey Minyard 
173525930707SCorey Minyard 		case SSIF_MULTI_2_PART:
17363d69d43bSCorey Minyard 			if (ssif_info->max_xmit_msg_size > 63)
17373d69d43bSCorey Minyard 				ssif_info->max_xmit_msg_size = 63;
173825930707SCorey Minyard 			if (ssif_info->max_recv_msg_size > 62)
173925930707SCorey Minyard 				ssif_info->max_recv_msg_size = 62;
174025930707SCorey Minyard 			break;
174125930707SCorey Minyard 
174225930707SCorey Minyard 		case SSIF_MULTI_n_PART:
174310042504SCorey Minyard 			/* We take whatever size given, but do some testing. */
174425930707SCorey Minyard 			break;
174525930707SCorey Minyard 
174625930707SCorey Minyard 		default:
174725930707SCorey Minyard 			/* Data is not sane, just give up. */
174825930707SCorey Minyard 			goto no_support;
174925930707SCorey Minyard 		}
175025930707SCorey Minyard 	} else {
175125930707SCorey Minyard  no_support:
175225930707SCorey Minyard 		/* Assume no multi-part or PEC support */
175383af4194SCorey Minyard 		dev_info(&ssif_info->client->dev,
175483af4194SCorey Minyard 			 "Error fetching SSIF: %d %d %2.2x, your system probably doesn't support this command so using defaults\n",
175525930707SCorey Minyard 			rv, len, resp[2]);
175625930707SCorey Minyard 
175725930707SCorey Minyard 		ssif_info->max_xmit_msg_size = 32;
175825930707SCorey Minyard 		ssif_info->max_recv_msg_size = 32;
175925930707SCorey Minyard 		ssif_info->multi_support = SSIF_NO_MULTI;
176025930707SCorey Minyard 		ssif_info->supports_pec = 0;
176125930707SCorey Minyard 	}
176225930707SCorey Minyard 
176310042504SCorey Minyard 	test_multipart_messages(client, ssif_info, resp);
176410042504SCorey Minyard 
176525930707SCorey Minyard 	/* Make sure the NMI timeout is cleared. */
176625930707SCorey Minyard 	msg[0] = IPMI_NETFN_APP_REQUEST << 2;
176725930707SCorey Minyard 	msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
176825930707SCorey Minyard 	msg[2] = WDT_PRE_TIMEOUT_INT;
176925930707SCorey Minyard 	rv = do_cmd(client, 3, msg, &len, resp);
177025930707SCorey Minyard 	if (rv || (len < 3) || (resp[2] != 0))
177183af4194SCorey Minyard 		dev_warn(&ssif_info->client->dev,
177283af4194SCorey Minyard 			 "Unable to clear message flags: %d %d %2.2x\n",
177325930707SCorey Minyard 			 rv, len, resp[2]);
177425930707SCorey Minyard 
177525930707SCorey Minyard 	/* Attempt to enable the event buffer. */
177625930707SCorey Minyard 	msg[0] = IPMI_NETFN_APP_REQUEST << 2;
177725930707SCorey Minyard 	msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
177825930707SCorey Minyard 	rv = do_cmd(client, 2, msg, &len, resp);
177925930707SCorey Minyard 	if (rv || (len < 4) || (resp[2] != 0)) {
178083af4194SCorey Minyard 		dev_warn(&ssif_info->client->dev,
178183af4194SCorey Minyard 			 "Error getting global enables: %d %d %2.2x\n",
178225930707SCorey Minyard 			 rv, len, resp[2]);
178325930707SCorey Minyard 		rv = 0; /* Not fatal */
178425930707SCorey Minyard 		goto found;
178525930707SCorey Minyard 	}
178625930707SCorey Minyard 
178791620521SCorey Minyard 	ssif_info->global_enables = resp[3];
178891620521SCorey Minyard 
178925930707SCorey Minyard 	if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) {
179025930707SCorey Minyard 		ssif_info->has_event_buffer = true;
179125930707SCorey Minyard 		/* buffer is already enabled, nothing to do. */
179225930707SCorey Minyard 		goto found;
179325930707SCorey Minyard 	}
179425930707SCorey Minyard 
179525930707SCorey Minyard 	msg[0] = IPMI_NETFN_APP_REQUEST << 2;
179625930707SCorey Minyard 	msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
179791620521SCorey Minyard 	msg[2] = ssif_info->global_enables | IPMI_BMC_EVT_MSG_BUFF;
179825930707SCorey Minyard 	rv = do_cmd(client, 3, msg, &len, resp);
179925930707SCorey Minyard 	if (rv || (len < 2)) {
180083af4194SCorey Minyard 		dev_warn(&ssif_info->client->dev,
180183af4194SCorey Minyard 			 "Error setting global enables: %d %d %2.2x\n",
180225930707SCorey Minyard 			 rv, len, resp[2]);
180325930707SCorey Minyard 		rv = 0; /* Not fatal */
180425930707SCorey Minyard 		goto found;
180525930707SCorey Minyard 	}
180625930707SCorey Minyard 
180791620521SCorey Minyard 	if (resp[2] == 0) {
180825930707SCorey Minyard 		/* A successful return means the event buffer is supported. */
180925930707SCorey Minyard 		ssif_info->has_event_buffer = true;
181091620521SCorey Minyard 		ssif_info->global_enables |= IPMI_BMC_EVT_MSG_BUFF;
181191620521SCorey Minyard 	}
181291620521SCorey Minyard 
1813bf2d0877SCorey Minyard 	/* Some systems don't behave well if you enable alerts. */
1814bf2d0877SCorey Minyard 	if (alerts_broken)
1815bf2d0877SCorey Minyard 		goto found;
1816bf2d0877SCorey Minyard 
181791620521SCorey Minyard 	msg[0] = IPMI_NETFN_APP_REQUEST << 2;
181891620521SCorey Minyard 	msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
181991620521SCorey Minyard 	msg[2] = ssif_info->global_enables | IPMI_BMC_RCV_MSG_INTR;
182091620521SCorey Minyard 	rv = do_cmd(client, 3, msg, &len, resp);
182191620521SCorey Minyard 	if (rv || (len < 2)) {
182283af4194SCorey Minyard 		dev_warn(&ssif_info->client->dev,
182383af4194SCorey Minyard 			 "Error setting global enables: %d %d %2.2x\n",
182491620521SCorey Minyard 			 rv, len, resp[2]);
182591620521SCorey Minyard 		rv = 0; /* Not fatal */
182691620521SCorey Minyard 		goto found;
182791620521SCorey Minyard 	}
182891620521SCorey Minyard 
182991620521SCorey Minyard 	if (resp[2] == 0) {
183091620521SCorey Minyard 		/* A successful return means the alert is supported. */
183191620521SCorey Minyard 		ssif_info->supports_alert = true;
183291620521SCorey Minyard 		ssif_info->global_enables |= IPMI_BMC_RCV_MSG_INTR;
183391620521SCorey Minyard 	}
183425930707SCorey Minyard 
183525930707SCorey Minyard  found:
183625930707SCorey Minyard 	if (ssif_dbg_probe) {
183783af4194SCorey Minyard 		dev_dbg(&ssif_info->client->dev,
183883af4194SCorey Minyard 		       "%s: i2c_probe found device at i2c address %x\n",
183983af4194SCorey Minyard 		       __func__, client->addr);
184025930707SCorey Minyard 	}
184125930707SCorey Minyard 
184225930707SCorey Minyard 	spin_lock_init(&ssif_info->lock);
18438230831cSCorey Minyard 	ssif_info->ssif_state = SSIF_IDLE;
1844e99e88a9SKees Cook 	timer_setup(&ssif_info->retry_timer, retry_timeout, 0);
1845a1466ec5SCorey Minyard 	timer_setup(&ssif_info->watch_timer, watch_timeout, 0);
184625930707SCorey Minyard 
184725930707SCorey Minyard 	for (i = 0; i < SSIF_NUM_STATS; i++)
184825930707SCorey Minyard 		atomic_set(&ssif_info->stats[i], 0);
184925930707SCorey Minyard 
185025930707SCorey Minyard 	if (ssif_info->supports_pec)
185125930707SCorey Minyard 		ssif_info->client->flags |= I2C_CLIENT_PEC;
185225930707SCorey Minyard 
185325930707SCorey Minyard 	ssif_info->handlers.owner = THIS_MODULE;
185425930707SCorey Minyard 	ssif_info->handlers.start_processing = ssif_start_processing;
1855a313dec6SCorey Minyard 	ssif_info->handlers.shutdown = shutdown_ssif;
185625930707SCorey Minyard 	ssif_info->handlers.get_smi_info = get_smi_info;
185725930707SCorey Minyard 	ssif_info->handlers.sender = sender;
185825930707SCorey Minyard 	ssif_info->handlers.request_events = request_events;
1859a1466ec5SCorey Minyard 	ssif_info->handlers.set_need_watch = ssif_set_need_watch;
186025930707SCorey Minyard 
186125930707SCorey Minyard 	{
186225930707SCorey Minyard 		unsigned int thread_num;
186325930707SCorey Minyard 
1864be8647d2SCorey Minyard 		thread_num = ((i2c_adapter_id(ssif_info->client->adapter)
1865be8647d2SCorey Minyard 			       << 8) |
186625930707SCorey Minyard 			      ssif_info->client->addr);
186725930707SCorey Minyard 		init_completion(&ssif_info->wake_thread);
186825930707SCorey Minyard 		ssif_info->thread = kthread_run(ipmi_ssif_thread, ssif_info,
186925930707SCorey Minyard 					       "kssif%4.4x", thread_num);
187025930707SCorey Minyard 		if (IS_ERR(ssif_info->thread)) {
187125930707SCorey Minyard 			rv = PTR_ERR(ssif_info->thread);
187225930707SCorey Minyard 			dev_notice(&ssif_info->client->dev,
187325930707SCorey Minyard 				   "Could not start kernel thread: error %d\n",
187425930707SCorey Minyard 				   rv);
187525930707SCorey Minyard 			goto out;
187625930707SCorey Minyard 		}
187725930707SCorey Minyard 	}
187825930707SCorey Minyard 
1879ac2673d5SCorey Minyard 	dev_set_drvdata(&ssif_info->client->dev, ssif_info);
1880ac2673d5SCorey Minyard 	rv = device_add_group(&ssif_info->client->dev,
1881ac2673d5SCorey Minyard 			      &ipmi_ssif_dev_attr_group);
1882ac2673d5SCorey Minyard 	if (rv) {
1883ac2673d5SCorey Minyard 		dev_err(&ssif_info->client->dev,
1884ac2673d5SCorey Minyard 			"Unable to add device attributes: error %d\n",
1885ac2673d5SCorey Minyard 			rv);
1886ac2673d5SCorey Minyard 		goto out;
1887ac2673d5SCorey Minyard 	}
1888ac2673d5SCorey Minyard 
188925930707SCorey Minyard 	rv = ipmi_register_smi(&ssif_info->handlers,
189025930707SCorey Minyard 			       ssif_info,
189125930707SCorey Minyard 			       &ssif_info->client->dev,
189225930707SCorey Minyard 			       slave_addr);
189325930707SCorey Minyard 	if (rv) {
189483af4194SCorey Minyard 		dev_err(&ssif_info->client->dev,
189583af4194SCorey Minyard 			"Unable to register device: error %d\n", rv);
1896ac2673d5SCorey Minyard 		goto out_remove_attr;
189725930707SCorey Minyard 	}
189825930707SCorey Minyard 
189925930707SCorey Minyard  out:
19000944d889SCorey Minyard 	if (rv) {
1901a8627cdaSGustavo A. R. Silva 		if (addr_info)
19020745dde6SCorey Minyard 			addr_info->client = NULL;
1903a8627cdaSGustavo A. R. Silva 
190483af4194SCorey Minyard 		dev_err(&ssif_info->client->dev,
190583af4194SCorey Minyard 			"Unable to start IPMI SSIF: %d\n", rv);
190634f35f8fSMian Yousaf Kaukab 		i2c_set_clientdata(client, NULL);
190725930707SCorey Minyard 		kfree(ssif_info);
19080944d889SCorey Minyard 	}
190925930707SCorey Minyard 	kfree(resp);
1910c4436c91SKamlakant Patel 	mutex_unlock(&ssif_infos_mutex);
191125930707SCorey Minyard 	return rv;
191225930707SCorey Minyard 
1913ac2673d5SCorey Minyard out_remove_attr:
1914ac2673d5SCorey Minyard 	device_remove_group(&ssif_info->client->dev, &ipmi_ssif_dev_attr_group);
1915ac2673d5SCorey Minyard 	dev_set_drvdata(&ssif_info->client->dev, NULL);
191625930707SCorey Minyard 	goto out;
191725930707SCorey Minyard }
191825930707SCorey Minyard 
new_ssif_client(int addr,char * adapter_name,int debug,int slave_addr,enum ipmi_addr_src addr_src,struct device * dev)191925930707SCorey Minyard static int new_ssif_client(int addr, char *adapter_name,
192025930707SCorey Minyard 			   int debug, int slave_addr,
19210944d889SCorey Minyard 			   enum ipmi_addr_src addr_src,
19220944d889SCorey Minyard 			   struct device *dev)
192325930707SCorey Minyard {
192425930707SCorey Minyard 	struct ssif_addr_info *addr_info;
192525930707SCorey Minyard 	int rv = 0;
192625930707SCorey Minyard 
192725930707SCorey Minyard 	mutex_lock(&ssif_infos_mutex);
192825930707SCorey Minyard 	if (ssif_info_find(addr, adapter_name, false)) {
192925930707SCorey Minyard 		rv = -EEXIST;
193025930707SCorey Minyard 		goto out_unlock;
193125930707SCorey Minyard 	}
193225930707SCorey Minyard 
193325930707SCorey Minyard 	addr_info = kzalloc(sizeof(*addr_info), GFP_KERNEL);
193425930707SCorey Minyard 	if (!addr_info) {
193525930707SCorey Minyard 		rv = -ENOMEM;
193625930707SCorey Minyard 		goto out_unlock;
193725930707SCorey Minyard 	}
193825930707SCorey Minyard 
193925930707SCorey Minyard 	if (adapter_name) {
194025930707SCorey Minyard 		addr_info->adapter_name = kstrdup(adapter_name, GFP_KERNEL);
194125930707SCorey Minyard 		if (!addr_info->adapter_name) {
194225930707SCorey Minyard 			kfree(addr_info);
194325930707SCorey Minyard 			rv = -ENOMEM;
194425930707SCorey Minyard 			goto out_unlock;
194525930707SCorey Minyard 		}
194625930707SCorey Minyard 	}
194725930707SCorey Minyard 
194825930707SCorey Minyard 	strncpy(addr_info->binfo.type, DEVICE_NAME,
194925930707SCorey Minyard 		sizeof(addr_info->binfo.type));
195025930707SCorey Minyard 	addr_info->binfo.addr = addr;
195125930707SCorey Minyard 	addr_info->binfo.platform_data = addr_info;
195225930707SCorey Minyard 	addr_info->debug = debug;
195325930707SCorey Minyard 	addr_info->slave_addr = slave_addr;
195425930707SCorey Minyard 	addr_info->addr_src = addr_src;
19550944d889SCorey Minyard 	addr_info->dev = dev;
19560944d889SCorey Minyard 
195787ff091cSCorey Minyard 	if (dev)
19580944d889SCorey Minyard 		dev_set_drvdata(dev, addr_info);
195925930707SCorey Minyard 
196025930707SCorey Minyard 	list_add_tail(&addr_info->link, &ssif_infos);
196125930707SCorey Minyard 
19622a556ce7SCorey Minyard 	/* Address list will get it */
196325930707SCorey Minyard 
196425930707SCorey Minyard out_unlock:
196525930707SCorey Minyard 	mutex_unlock(&ssif_infos_mutex);
196625930707SCorey Minyard 	return rv;
196725930707SCorey Minyard }
196825930707SCorey Minyard 
free_ssif_clients(void)196925930707SCorey Minyard static void free_ssif_clients(void)
197025930707SCorey Minyard {
197125930707SCorey Minyard 	struct ssif_addr_info *info, *tmp;
197225930707SCorey Minyard 
197325930707SCorey Minyard 	mutex_lock(&ssif_infos_mutex);
197425930707SCorey Minyard 	list_for_each_entry_safe(info, tmp, &ssif_infos, link) {
197525930707SCorey Minyard 		list_del(&info->link);
197625930707SCorey Minyard 		kfree(info->adapter_name);
197725930707SCorey Minyard 		kfree(info);
197825930707SCorey Minyard 	}
197925930707SCorey Minyard 	mutex_unlock(&ssif_infos_mutex);
198025930707SCorey Minyard }
198125930707SCorey Minyard 
ssif_address_list(void)198225930707SCorey Minyard static unsigned short *ssif_address_list(void)
198325930707SCorey Minyard {
198425930707SCorey Minyard 	struct ssif_addr_info *info;
1985c75c5075SCorey Minyard 	unsigned int count = 0, i = 0;
198625930707SCorey Minyard 	unsigned short *address_list;
198725930707SCorey Minyard 
198825930707SCorey Minyard 	list_for_each_entry(info, &ssif_infos, link)
198925930707SCorey Minyard 		count++;
199025930707SCorey Minyard 
19916396bb22SKees Cook 	address_list = kcalloc(count + 1, sizeof(*address_list),
19926396bb22SKees Cook 			       GFP_KERNEL);
199325930707SCorey Minyard 	if (!address_list)
199425930707SCorey Minyard 		return NULL;
199525930707SCorey Minyard 
199625930707SCorey Minyard 	list_for_each_entry(info, &ssif_infos, link) {
199725930707SCorey Minyard 		unsigned short addr = info->binfo.addr;
199825930707SCorey Minyard 		int j;
199925930707SCorey Minyard 
200025930707SCorey Minyard 		for (j = 0; j < i; j++) {
200125930707SCorey Minyard 			if (address_list[j] == addr)
2002c75c5075SCorey Minyard 				/* Found a dup. */
2003c75c5075SCorey Minyard 				break;
200425930707SCorey Minyard 		}
2005c75c5075SCorey Minyard 		if (j == i) /* Didn't find it in the list. */
2006c75c5075SCorey Minyard 			address_list[i++] = addr;
200725930707SCorey Minyard 	}
200825930707SCorey Minyard 	address_list[i] = I2C_CLIENT_END;
200925930707SCorey Minyard 
201025930707SCorey Minyard 	return address_list;
201125930707SCorey Minyard }
201225930707SCorey Minyard 
201325930707SCorey Minyard #ifdef CONFIG_ACPI
20145186cf9cSMathias Krause static const struct acpi_device_id ssif_acpi_match[] = {
201525930707SCorey Minyard 	{ "IPI0001", 0 },
201625930707SCorey Minyard 	{ },
201725930707SCorey Minyard };
201825930707SCorey Minyard MODULE_DEVICE_TABLE(acpi, ssif_acpi_match);
201925930707SCorey Minyard #endif
202025930707SCorey Minyard 
202125930707SCorey Minyard #ifdef CONFIG_DMI
dmi_ipmi_probe(struct platform_device * pdev)20220944d889SCorey Minyard static int dmi_ipmi_probe(struct platform_device *pdev)
202325930707SCorey Minyard {
202495e300c0SCorey Minyard 	u8 slave_addr = 0;
20250944d889SCorey Minyard 	u16 i2c_addr;
20260944d889SCorey Minyard 	int rv;
202725930707SCorey Minyard 
20280944d889SCorey Minyard 	if (!ssif_trydmi)
20290944d889SCorey Minyard 		return -ENODEV;
203025930707SCorey Minyard 
20310944d889SCorey Minyard 	rv = device_property_read_u16(&pdev->dev, "i2c-addr", &i2c_addr);
20320944d889SCorey Minyard 	if (rv) {
203325880f7dSJoe Perches 		dev_warn(&pdev->dev, "No i2c-addr property\n");
20340944d889SCorey Minyard 		return -ENODEV;
203525930707SCorey Minyard 	}
203625930707SCorey Minyard 
20370944d889SCorey Minyard 	rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr);
20380944d889SCorey Minyard 	if (rv)
2039ed6c3a6dSCorey Minyard 		slave_addr = 0x20;
204025930707SCorey Minyard 
20410944d889SCorey Minyard 	return new_ssif_client(i2c_addr, NULL, 0,
20420944d889SCorey Minyard 			       slave_addr, SI_SMBIOS, &pdev->dev);
204325930707SCorey Minyard }
204425930707SCorey Minyard #else
dmi_ipmi_probe(struct platform_device * pdev)20450944d889SCorey Minyard static int dmi_ipmi_probe(struct platform_device *pdev)
20460944d889SCorey Minyard {
20470944d889SCorey Minyard 	return -ENODEV;
20480944d889SCorey Minyard }
204925930707SCorey Minyard #endif
205025930707SCorey Minyard 
205125930707SCorey Minyard static const struct i2c_device_id ssif_id[] = {
205225930707SCorey Minyard 	{ DEVICE_NAME, 0 },
205325930707SCorey Minyard 	{ }
205425930707SCorey Minyard };
205525930707SCorey Minyard MODULE_DEVICE_TABLE(i2c, ssif_id);
205625930707SCorey Minyard 
205725930707SCorey Minyard static struct i2c_driver ssif_i2c_driver = {
205825930707SCorey Minyard 	.class		= I2C_CLASS_HWMON,
205925930707SCorey Minyard 	.driver		= {
206025930707SCorey Minyard 		.name			= DEVICE_NAME
206125930707SCorey Minyard 	},
2062e64c82b8SUwe Kleine-König 	.probe		= ssif_probe,
206325930707SCorey Minyard 	.remove		= ssif_remove,
206491620521SCorey Minyard 	.alert		= ssif_alert,
206525930707SCorey Minyard 	.id_table	= ssif_id,
206625930707SCorey Minyard 	.detect		= ssif_detect
206725930707SCorey Minyard };
206825930707SCorey Minyard 
ssif_platform_probe(struct platform_device * dev)20690944d889SCorey Minyard static int ssif_platform_probe(struct platform_device *dev)
20700944d889SCorey Minyard {
20710944d889SCorey Minyard 	return dmi_ipmi_probe(dev);
20720944d889SCorey Minyard }
20730944d889SCorey Minyard 
ssif_platform_remove(struct platform_device * dev)20740944d889SCorey Minyard static int ssif_platform_remove(struct platform_device *dev)
20750944d889SCorey Minyard {
20760944d889SCorey Minyard 	struct ssif_addr_info *addr_info = dev_get_drvdata(&dev->dev);
20770944d889SCorey Minyard 
20780944d889SCorey Minyard 	mutex_lock(&ssif_infos_mutex);
20790944d889SCorey Minyard 	list_del(&addr_info->link);
20800944d889SCorey Minyard 	kfree(addr_info);
20810944d889SCorey Minyard 	mutex_unlock(&ssif_infos_mutex);
20820944d889SCorey Minyard 	return 0;
20830944d889SCorey Minyard }
20840944d889SCorey Minyard 
2085b3096c70SCorey Minyard static const struct platform_device_id ssif_plat_ids[] = {
2086b3096c70SCorey Minyard     { "dmi-ipmi-ssif", 0 },
2087b3096c70SCorey Minyard     { }
2088b3096c70SCorey Minyard };
2089b3096c70SCorey Minyard 
20900944d889SCorey Minyard static struct platform_driver ipmi_driver = {
20910944d889SCorey Minyard 	.driver = {
20920944d889SCorey Minyard 		.name = DEVICE_NAME,
20930944d889SCorey Minyard 	},
20940944d889SCorey Minyard 	.probe		= ssif_platform_probe,
20950944d889SCorey Minyard 	.remove		= ssif_platform_remove,
2096b3096c70SCorey Minyard 	.id_table       = ssif_plat_ids
20970944d889SCorey Minyard };
20980944d889SCorey Minyard 
init_ipmi_ssif(void)2099ec7174f6SXiu Jianfeng static int __init init_ipmi_ssif(void)
210025930707SCorey Minyard {
210125930707SCorey Minyard 	int i;
210225930707SCorey Minyard 	int rv;
210325930707SCorey Minyard 
210425930707SCorey Minyard 	if (initialized)
210525930707SCorey Minyard 		return 0;
210625930707SCorey Minyard 
210725930707SCorey Minyard 	pr_info("IPMI SSIF Interface driver\n");
210825930707SCorey Minyard 
210925930707SCorey Minyard 	/* build list for i2c from addr list */
211025930707SCorey Minyard 	for (i = 0; i < num_addrs; i++) {
211125930707SCorey Minyard 		rv = new_ssif_client(addr[i], adapter_name[i],
211225930707SCorey Minyard 				     dbg[i], slave_addrs[i],
21130944d889SCorey Minyard 				     SI_HARDCODED, NULL);
2114d467f7a4SCorey Minyard 		if (rv)
211525880f7dSJoe Perches 			pr_err("Couldn't add hardcoded device at addr 0x%x\n",
211625930707SCorey Minyard 			       addr[i]);
211725930707SCorey Minyard 	}
211825930707SCorey Minyard 
211925930707SCorey Minyard 	if (ssif_tryacpi)
212025930707SCorey Minyard 		ssif_i2c_driver.driver.acpi_match_table	=
212125930707SCorey Minyard 			ACPI_PTR(ssif_acpi_match);
21220944d889SCorey Minyard 
21230944d889SCorey Minyard 	if (ssif_trydmi) {
21240944d889SCorey Minyard 		rv = platform_driver_register(&ipmi_driver);
21250944d889SCorey Minyard 		if (rv)
212625880f7dSJoe Perches 			pr_err("Unable to register driver: %d\n", rv);
21272cd0e544SKefeng Wang 		else
21282cd0e544SKefeng Wang 			platform_registered = true;
21290944d889SCorey Minyard 	}
21300944d889SCorey Minyard 
213125930707SCorey Minyard 	ssif_i2c_driver.address_list = ssif_address_list();
213225930707SCorey Minyard 
213325930707SCorey Minyard 	rv = i2c_add_driver(&ssif_i2c_driver);
213425930707SCorey Minyard 	if (!rv)
213525930707SCorey Minyard 		initialized = true;
213625930707SCorey Minyard 
213725930707SCorey Minyard 	return rv;
213825930707SCorey Minyard }
213925930707SCorey Minyard module_init(init_ipmi_ssif);
214025930707SCorey Minyard 
cleanup_ipmi_ssif(void)2141ec7174f6SXiu Jianfeng static void __exit cleanup_ipmi_ssif(void)
214225930707SCorey Minyard {
214325930707SCorey Minyard 	if (!initialized)
214425930707SCorey Minyard 		return;
214525930707SCorey Minyard 
214625930707SCorey Minyard 	initialized = false;
214725930707SCorey Minyard 
214825930707SCorey Minyard 	i2c_del_driver(&ssif_i2c_driver);
214925930707SCorey Minyard 
215036e398d7SCorey Minyard 	kfree(ssif_i2c_driver.address_list);
215136e398d7SCorey Minyard 
21522cd0e544SKefeng Wang 	if (ssif_trydmi && platform_registered)
21530944d889SCorey Minyard 		platform_driver_unregister(&ipmi_driver);
21540944d889SCorey Minyard 
215525930707SCorey Minyard 	free_ssif_clients();
215625930707SCorey Minyard }
215725930707SCorey Minyard module_exit(cleanup_ipmi_ssif);
215825930707SCorey Minyard 
21590944d889SCorey Minyard MODULE_ALIAS("platform:dmi-ipmi-ssif");
216025930707SCorey Minyard MODULE_AUTHOR("Todd C Davis <todd.c.davis@intel.com>, Corey Minyard <minyard@acm.org>");
216125930707SCorey Minyard MODULE_DESCRIPTION("IPMI driver for management controllers on a SMBus");
216225930707SCorey Minyard MODULE_LICENSE("GPL");
2163