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 {
983bd7c8ff9SAnna-Maria Behnsen /* Wait a jiffy 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;
1371*88f65f90SCorey Minyard else {
1372*88f65f90SCorey Minyard if (len < 3) {
1373*88f65f90SCorey Minyard rv = -ENODEV;
1374*88f65f90SCorey Minyard } else {
1375*88f65f90SCorey Minyard struct ipmi_device_id id;
1376*88f65f90SCorey Minyard
1377*88f65f90SCorey Minyard rv = ipmi_demangle_device_id(resp[0] >> 2, resp[1],
1378*88f65f90SCorey Minyard resp + 2, len - 2, &id);
1379*88f65f90SCorey Minyard if (rv)
1380*88f65f90SCorey Minyard rv = -ENODEV; /* Error means a BMC probably isn't there. */
1381*88f65f90SCorey Minyard }
1382*88f65f90SCorey Minyard if (!rv && info)
1383d134ad25SJason Wang strscpy(info->type, DEVICE_NAME, I2C_NAME_SIZE);
1384*88f65f90SCorey Minyard }
138525930707SCorey Minyard kfree(resp);
138625930707SCorey Minyard return rv;
138725930707SCorey Minyard }
138825930707SCorey Minyard
strcmp_nospace(char * s1,char * s2)1389b0e9aaa9SCorey Minyard static int strcmp_nospace(char *s1, char *s2)
1390b0e9aaa9SCorey Minyard {
1391b0e9aaa9SCorey Minyard while (*s1 && *s2) {
1392b0e9aaa9SCorey Minyard while (isspace(*s1))
1393b0e9aaa9SCorey Minyard s1++;
1394b0e9aaa9SCorey Minyard while (isspace(*s2))
1395b0e9aaa9SCorey Minyard s2++;
1396b0e9aaa9SCorey Minyard if (*s1 > *s2)
1397b0e9aaa9SCorey Minyard return 1;
1398b0e9aaa9SCorey Minyard if (*s1 < *s2)
1399b0e9aaa9SCorey Minyard return -1;
1400b0e9aaa9SCorey Minyard s1++;
1401b0e9aaa9SCorey Minyard s2++;
1402b0e9aaa9SCorey Minyard }
1403b0e9aaa9SCorey Minyard return 0;
1404b0e9aaa9SCorey Minyard }
1405b0e9aaa9SCorey Minyard
ssif_info_find(unsigned short addr,char * adapter_name,bool match_null_name)140625930707SCorey Minyard static struct ssif_addr_info *ssif_info_find(unsigned short addr,
140725930707SCorey Minyard char *adapter_name,
140825930707SCorey Minyard bool match_null_name)
140925930707SCorey Minyard {
141025930707SCorey Minyard struct ssif_addr_info *info, *found = NULL;
141125930707SCorey Minyard
141225930707SCorey Minyard restart:
141325930707SCorey Minyard list_for_each_entry(info, &ssif_infos, link) {
141425930707SCorey Minyard if (info->binfo.addr == addr) {
1415b8d72e32SCorey Minyard if (info->addr_src == SI_SMBIOS && !info->adapter_name)
1416c4436c91SKamlakant Patel info->adapter_name = kstrdup(adapter_name,
1417c4436c91SKamlakant Patel GFP_KERNEL);
1418c4436c91SKamlakant Patel
141925930707SCorey Minyard if (info->adapter_name || adapter_name) {
142025930707SCorey Minyard if (!info->adapter_name != !adapter_name) {
142125930707SCorey Minyard /* One is NULL and one is not */
142225930707SCorey Minyard continue;
142325930707SCorey Minyard }
1424b0e9aaa9SCorey Minyard if (adapter_name &&
1425b0e9aaa9SCorey Minyard strcmp_nospace(info->adapter_name,
1426b0e9aaa9SCorey Minyard adapter_name))
1427b0e9aaa9SCorey Minyard /* Names do not match */
142825930707SCorey Minyard continue;
142925930707SCorey Minyard }
143025930707SCorey Minyard found = info;
143125930707SCorey Minyard break;
143225930707SCorey Minyard }
143325930707SCorey Minyard }
143425930707SCorey Minyard
143525930707SCorey Minyard if (!found && match_null_name) {
143625930707SCorey Minyard /* Try to get an exact match first, then try with a NULL name */
143725930707SCorey Minyard adapter_name = NULL;
143825930707SCorey Minyard match_null_name = false;
143925930707SCorey Minyard goto restart;
144025930707SCorey Minyard }
144125930707SCorey Minyard
144225930707SCorey Minyard return found;
144325930707SCorey Minyard }
144425930707SCorey Minyard
check_acpi(struct ssif_info * ssif_info,struct device * dev)144525930707SCorey Minyard static bool check_acpi(struct ssif_info *ssif_info, struct device *dev)
144625930707SCorey Minyard {
144725930707SCorey Minyard #ifdef CONFIG_ACPI
144825930707SCorey Minyard acpi_handle acpi_handle;
144925930707SCorey Minyard
145025930707SCorey Minyard acpi_handle = ACPI_HANDLE(dev);
145125930707SCorey Minyard if (acpi_handle) {
145225930707SCorey Minyard ssif_info->addr_source = SI_ACPI;
145325930707SCorey Minyard ssif_info->addr_info.acpi_info.acpi_handle = acpi_handle;
1454e87443a5SCorey Minyard request_module_nowait("acpi_ipmi");
145525930707SCorey Minyard return true;
145625930707SCorey Minyard }
145725930707SCorey Minyard #endif
145825930707SCorey Minyard return false;
145925930707SCorey Minyard }
146025930707SCorey Minyard
find_slave_address(struct i2c_client * client,int slave_addr)146194671710SCorey Minyard static int find_slave_address(struct i2c_client *client, int slave_addr)
146294671710SCorey Minyard {
14630944d889SCorey Minyard #ifdef CONFIG_IPMI_DMI_DECODE
14640944d889SCorey Minyard if (!slave_addr)
14650944d889SCorey Minyard slave_addr = ipmi_dmi_get_slave_addr(
146695e300c0SCorey Minyard SI_TYPE_INVALID,
14670944d889SCorey Minyard i2c_adapter_id(client->adapter),
14680944d889SCorey Minyard client->addr);
14690944d889SCorey Minyard #endif
147094671710SCorey Minyard
147194671710SCorey Minyard return slave_addr;
147294671710SCorey Minyard }
147394671710SCorey Minyard
start_multipart_test(struct i2c_client * client,unsigned char * msg,bool do_middle)147410042504SCorey Minyard static int start_multipart_test(struct i2c_client *client,
147510042504SCorey Minyard unsigned char *msg, bool do_middle)
147610042504SCorey Minyard {
147710042504SCorey Minyard int retry_cnt = SSIF_SEND_RETRIES, ret;
147810042504SCorey Minyard
147910042504SCorey Minyard retry_write:
148010042504SCorey Minyard ret = i2c_smbus_write_block_data(client,
148110042504SCorey Minyard SSIF_IPMI_MULTI_PART_REQUEST_START,
148210042504SCorey Minyard 32, msg);
148310042504SCorey Minyard if (ret) {
148410042504SCorey Minyard retry_cnt--;
148500bb7e76SCorey Minyard if (retry_cnt > 0) {
148600bb7e76SCorey Minyard msleep(SSIF_REQ_RETRY_MSEC);
148710042504SCorey Minyard goto retry_write;
148800bb7e76SCorey Minyard }
148910042504SCorey 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");
149010042504SCorey Minyard return ret;
149110042504SCorey Minyard }
149210042504SCorey Minyard
149310042504SCorey Minyard if (!do_middle)
149410042504SCorey Minyard return 0;
149510042504SCorey Minyard
149610042504SCorey Minyard ret = i2c_smbus_write_block_data(client,
149710042504SCorey Minyard SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE,
149810042504SCorey Minyard 32, msg + 32);
149910042504SCorey Minyard if (ret) {
150010042504SCorey 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");
150110042504SCorey Minyard return ret;
150210042504SCorey Minyard }
150310042504SCorey Minyard
150410042504SCorey Minyard return 0;
150510042504SCorey Minyard }
150610042504SCorey Minyard
test_multipart_messages(struct i2c_client * client,struct ssif_info * ssif_info,unsigned char * resp)150710042504SCorey Minyard static void test_multipart_messages(struct i2c_client *client,
150810042504SCorey Minyard struct ssif_info *ssif_info,
150910042504SCorey Minyard unsigned char *resp)
151010042504SCorey Minyard {
151110042504SCorey Minyard unsigned char msg[65];
151210042504SCorey Minyard int ret;
151310042504SCorey Minyard bool do_middle;
151410042504SCorey Minyard
151510042504SCorey Minyard if (ssif_info->max_xmit_msg_size <= 32)
151610042504SCorey Minyard return;
151710042504SCorey Minyard
151810042504SCorey Minyard do_middle = ssif_info->max_xmit_msg_size > 63;
151910042504SCorey Minyard
152010042504SCorey Minyard memset(msg, 0, sizeof(msg));
152110042504SCorey Minyard msg[0] = IPMI_NETFN_APP_REQUEST << 2;
152210042504SCorey Minyard msg[1] = IPMI_GET_DEVICE_ID_CMD;
152310042504SCorey Minyard
152410042504SCorey Minyard /*
152510042504SCorey Minyard * The specification is all messed up dealing with sending
152610042504SCorey Minyard * multi-part messages. Per what the specification says, it
152710042504SCorey Minyard * is impossible to send a message that is a multiple of 32
152810042504SCorey Minyard * bytes, except for 32 itself. It talks about a "start"
152910042504SCorey Minyard * transaction (cmd=6) that must be 32 bytes, "middle"
153010042504SCorey Minyard * transaction (cmd=7) that must be 32 bytes, and an "end"
153110042504SCorey Minyard * transaction. The "end" transaction is shown as cmd=7 in
153210042504SCorey Minyard * the text, but if that's the case there is no way to
153310042504SCorey Minyard * differentiate between a middle and end part except the
153410042504SCorey Minyard * length being less than 32. But there is a table at the far
153510042504SCorey Minyard * end of the section (that I had never noticed until someone
153610042504SCorey Minyard * pointed it out to me) that mentions it as cmd=8.
153710042504SCorey Minyard *
153810042504SCorey Minyard * After some thought, I think the example is wrong and the
153910042504SCorey Minyard * end transaction should be cmd=8. But some systems don't
154010042504SCorey Minyard * implement cmd=8, they use a zero-length end transaction,
154110042504SCorey Minyard * even though that violates the SMBus specification.
154210042504SCorey Minyard *
154310042504SCorey Minyard * So, to work around this, this code tests if cmd=8 works.
154410042504SCorey Minyard * If it does, then we use that. If not, it tests zero-
154510042504SCorey Minyard * byte end transactions. If that works, good. If not,
154610042504SCorey Minyard * we only allow 63-byte transactions max.
154710042504SCorey Minyard */
154810042504SCorey Minyard
154910042504SCorey Minyard ret = start_multipart_test(client, msg, do_middle);
155010042504SCorey Minyard if (ret)
155110042504SCorey Minyard goto out_no_multi_part;
155210042504SCorey Minyard
155310042504SCorey Minyard ret = i2c_smbus_write_block_data(client,
155410042504SCorey Minyard SSIF_IPMI_MULTI_PART_REQUEST_END,
155510042504SCorey Minyard 1, msg + 64);
155610042504SCorey Minyard
155710042504SCorey Minyard if (!ret)
155810042504SCorey Minyard ret = read_response(client, resp);
155910042504SCorey Minyard
156010042504SCorey Minyard if (ret > 0) {
156110042504SCorey Minyard /* End transactions work, we are good. */
156210042504SCorey Minyard ssif_info->cmd8_works = true;
156310042504SCorey Minyard return;
156410042504SCorey Minyard }
156510042504SCorey Minyard
156610042504SCorey Minyard ret = start_multipart_test(client, msg, do_middle);
156710042504SCorey Minyard if (ret) {
156810042504SCorey Minyard dev_err(&client->dev, "Second multipart test failed.\n");
156910042504SCorey Minyard goto out_no_multi_part;
157010042504SCorey Minyard }
157110042504SCorey Minyard
157210042504SCorey Minyard ret = i2c_smbus_write_block_data(client,
157310042504SCorey Minyard SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE,
157410042504SCorey Minyard 0, msg + 64);
157510042504SCorey Minyard if (!ret)
157610042504SCorey Minyard ret = read_response(client, resp);
157710042504SCorey Minyard if (ret > 0)
157810042504SCorey Minyard /* Zero-size end parts work, use those. */
157910042504SCorey Minyard return;
158010042504SCorey Minyard
158110042504SCorey Minyard /* Limit to 63 bytes and use a short middle command to mark the end. */
158210042504SCorey Minyard if (ssif_info->max_xmit_msg_size > 63)
158310042504SCorey Minyard ssif_info->max_xmit_msg_size = 63;
158410042504SCorey Minyard return;
158510042504SCorey Minyard
158610042504SCorey Minyard out_no_multi_part:
158710042504SCorey Minyard ssif_info->max_xmit_msg_size = 32;
158810042504SCorey Minyard return;
158910042504SCorey Minyard }
159010042504SCorey Minyard
159191620521SCorey Minyard /*
159291620521SCorey Minyard * Global enables we care about.
159391620521SCorey Minyard */
159491620521SCorey Minyard #define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR | \
159591620521SCorey Minyard IPMI_BMC_EVT_MSG_INTR)
159691620521SCorey Minyard
ssif_remove_dup(struct i2c_client * client)1597c4436c91SKamlakant Patel static void ssif_remove_dup(struct i2c_client *client)
1598c4436c91SKamlakant Patel {
1599c4436c91SKamlakant Patel struct ssif_info *ssif_info = i2c_get_clientdata(client);
1600c4436c91SKamlakant Patel
1601c4436c91SKamlakant Patel ipmi_unregister_smi(ssif_info->intf);
1602c4436c91SKamlakant Patel kfree(ssif_info);
1603c4436c91SKamlakant Patel }
1604c4436c91SKamlakant Patel
ssif_add_infos(struct i2c_client * client)1605c4436c91SKamlakant Patel static int ssif_add_infos(struct i2c_client *client)
1606c4436c91SKamlakant Patel {
1607c4436c91SKamlakant Patel struct ssif_addr_info *info;
1608c4436c91SKamlakant Patel
1609c4436c91SKamlakant Patel info = kzalloc(sizeof(*info), GFP_KERNEL);
1610c4436c91SKamlakant Patel if (!info)
1611c4436c91SKamlakant Patel return -ENOMEM;
1612c4436c91SKamlakant Patel info->addr_src = SI_ACPI;
1613c4436c91SKamlakant Patel info->client = client;
1614c4436c91SKamlakant Patel info->adapter_name = kstrdup(client->adapter->name, GFP_KERNEL);
1615c5586d0fSJiasheng Jiang if (!info->adapter_name) {
1616c5586d0fSJiasheng Jiang kfree(info);
1617c5586d0fSJiasheng Jiang return -ENOMEM;
1618c5586d0fSJiasheng Jiang }
1619c5586d0fSJiasheng Jiang
1620c4436c91SKamlakant Patel info->binfo.addr = client->addr;
1621c4436c91SKamlakant Patel list_add_tail(&info->link, &ssif_infos);
1622c4436c91SKamlakant Patel return 0;
1623c4436c91SKamlakant Patel }
1624c4436c91SKamlakant Patel
1625c4436c91SKamlakant Patel /*
1626c4436c91SKamlakant Patel * Prefer ACPI over SMBIOS, if both are available.
1627c4436c91SKamlakant Patel * So if we get an ACPI interface and have already registered a SMBIOS
1628c4436c91SKamlakant Patel * interface at the same address, remove the SMBIOS and add the ACPI one.
1629c4436c91SKamlakant Patel */
ssif_check_and_remove(struct i2c_client * client,struct ssif_info * ssif_info)1630c4436c91SKamlakant Patel static int ssif_check_and_remove(struct i2c_client *client,
1631c4436c91SKamlakant Patel struct ssif_info *ssif_info)
1632c4436c91SKamlakant Patel {
1633c4436c91SKamlakant Patel struct ssif_addr_info *info;
1634c4436c91SKamlakant Patel
1635c4436c91SKamlakant Patel list_for_each_entry(info, &ssif_infos, link) {
1636c4436c91SKamlakant Patel if (!info->client)
1637c4436c91SKamlakant Patel return 0;
1638c4436c91SKamlakant Patel if (!strcmp(info->adapter_name, client->adapter->name) &&
1639c4436c91SKamlakant Patel info->binfo.addr == client->addr) {
1640c4436c91SKamlakant Patel if (info->addr_src == SI_ACPI)
1641c4436c91SKamlakant Patel return -EEXIST;
1642c4436c91SKamlakant Patel
1643c4436c91SKamlakant Patel if (ssif_info->addr_source == SI_ACPI &&
1644c4436c91SKamlakant Patel info->addr_src == SI_SMBIOS) {
1645c4436c91SKamlakant Patel dev_info(&client->dev,
1646c4436c91SKamlakant Patel "Removing %s-specified SSIF interface in favor of ACPI\n",
1647c4436c91SKamlakant Patel ipmi_addr_src_to_str(info->addr_src));
1648c4436c91SKamlakant Patel ssif_remove_dup(info->client);
1649c4436c91SKamlakant Patel return 0;
1650c4436c91SKamlakant Patel }
1651c4436c91SKamlakant Patel }
1652c4436c91SKamlakant Patel }
1653c4436c91SKamlakant Patel return 0;
1654c4436c91SKamlakant Patel }
1655c4436c91SKamlakant Patel
ssif_probe(struct i2c_client * client)16560924c5a0SStephen Kitt static int ssif_probe(struct i2c_client *client)
165725930707SCorey Minyard {
165825930707SCorey Minyard unsigned char msg[3];
165925930707SCorey Minyard unsigned char *resp;
166025930707SCorey Minyard struct ssif_info *ssif_info;
166125930707SCorey Minyard int rv = 0;
16628d10ea15STom Rix int len = 0;
166325930707SCorey Minyard int i;
166425930707SCorey Minyard u8 slave_addr = 0;
166525930707SCorey Minyard struct ssif_addr_info *addr_info = NULL;
166625930707SCorey Minyard
1667c4436c91SKamlakant Patel mutex_lock(&ssif_infos_mutex);
166825930707SCorey Minyard resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
1669c4436c91SKamlakant Patel if (!resp) {
1670c4436c91SKamlakant Patel mutex_unlock(&ssif_infos_mutex);
167125930707SCorey Minyard return -ENOMEM;
1672c4436c91SKamlakant Patel }
167325930707SCorey Minyard
167425930707SCorey Minyard ssif_info = kzalloc(sizeof(*ssif_info), GFP_KERNEL);
167525930707SCorey Minyard if (!ssif_info) {
167625930707SCorey Minyard kfree(resp);
1677c4436c91SKamlakant Patel mutex_unlock(&ssif_infos_mutex);
167825930707SCorey Minyard return -ENOMEM;
167925930707SCorey Minyard }
168025930707SCorey Minyard
168125930707SCorey Minyard if (!check_acpi(ssif_info, &client->dev)) {
168225930707SCorey Minyard addr_info = ssif_info_find(client->addr, client->adapter->name,
168325930707SCorey Minyard true);
168425930707SCorey Minyard if (!addr_info) {
168525930707SCorey Minyard /* Must have come in through sysfs. */
168625930707SCorey Minyard ssif_info->addr_source = SI_HOTMOD;
168725930707SCorey Minyard } else {
168825930707SCorey Minyard ssif_info->addr_source = addr_info->addr_src;
168925930707SCorey Minyard ssif_info->ssif_debug = addr_info->debug;
169025930707SCorey Minyard ssif_info->addr_info = addr_info->addr_info;
16910944d889SCorey Minyard addr_info->client = client;
169225930707SCorey Minyard slave_addr = addr_info->slave_addr;
169325930707SCorey Minyard }
169425930707SCorey Minyard }
169525930707SCorey Minyard
169634f35f8fSMian Yousaf Kaukab ssif_info->client = client;
169734f35f8fSMian Yousaf Kaukab i2c_set_clientdata(client, ssif_info);
169834f35f8fSMian Yousaf Kaukab
1699c4436c91SKamlakant Patel rv = ssif_check_and_remove(client, ssif_info);
1700c4436c91SKamlakant Patel /* If rv is 0 and addr source is not SI_ACPI, continue probing */
1701c4436c91SKamlakant Patel if (!rv && ssif_info->addr_source == SI_ACPI) {
1702c4436c91SKamlakant Patel rv = ssif_add_infos(client);
1703c4436c91SKamlakant Patel if (rv) {
1704c4436c91SKamlakant Patel dev_err(&client->dev, "Out of memory!, exiting ..\n");
1705c4436c91SKamlakant Patel goto out;
1706c4436c91SKamlakant Patel }
1707c4436c91SKamlakant Patel } else if (rv) {
1708c4436c91SKamlakant Patel dev_err(&client->dev, "Not probing, Interface already present\n");
1709c4436c91SKamlakant Patel goto out;
1710c4436c91SKamlakant Patel }
1711c4436c91SKamlakant Patel
171294671710SCorey Minyard slave_addr = find_slave_address(client, slave_addr);
171394671710SCorey Minyard
171483af4194SCorey Minyard dev_info(&client->dev,
171583af4194SCorey Minyard "Trying %s-specified SSIF interface at i2c address 0x%x, adapter %s, slave address 0x%x\n",
171625930707SCorey Minyard ipmi_addr_src_to_str(ssif_info->addr_source),
171725930707SCorey Minyard client->addr, client->adapter->name, slave_addr);
171825930707SCorey Minyard
1719*88f65f90SCorey Minyard /*
1720*88f65f90SCorey Minyard * Send a get device id command and validate its response to
1721*88f65f90SCorey Minyard * make sure a valid BMC is there.
1722*88f65f90SCorey Minyard */
1723*88f65f90SCorey Minyard rv = ssif_detect(client, NULL);
1724*88f65f90SCorey Minyard if (rv) {
1725*88f65f90SCorey Minyard dev_err(&client->dev, "Not present\n");
1726*88f65f90SCorey Minyard goto out;
1727*88f65f90SCorey Minyard }
1728*88f65f90SCorey Minyard
172925930707SCorey Minyard /* Now check for system interface capabilities */
173025930707SCorey Minyard msg[0] = IPMI_NETFN_APP_REQUEST << 2;
173125930707SCorey Minyard msg[1] = IPMI_GET_SYSTEM_INTERFACE_CAPABILITIES_CMD;
173225930707SCorey Minyard msg[2] = 0; /* SSIF */
173325930707SCorey Minyard rv = do_cmd(client, 3, msg, &len, resp);
173425930707SCorey Minyard if (!rv && (len >= 3) && (resp[2] == 0)) {
173525930707SCorey Minyard if (len < 7) {
173625930707SCorey Minyard if (ssif_dbg_probe)
173783af4194SCorey Minyard dev_dbg(&ssif_info->client->dev,
173883af4194SCorey Minyard "SSIF info too short: %d\n", len);
173925930707SCorey Minyard goto no_support;
174025930707SCorey Minyard }
174125930707SCorey Minyard
174225930707SCorey Minyard /* Got a good SSIF response, handle it. */
174325930707SCorey Minyard ssif_info->max_xmit_msg_size = resp[5];
174425930707SCorey Minyard ssif_info->max_recv_msg_size = resp[6];
174525930707SCorey Minyard ssif_info->multi_support = (resp[4] >> 6) & 0x3;
174625930707SCorey Minyard ssif_info->supports_pec = (resp[4] >> 3) & 0x1;
174725930707SCorey Minyard
174825930707SCorey Minyard /* Sanitize the data */
174925930707SCorey Minyard switch (ssif_info->multi_support) {
175025930707SCorey Minyard case SSIF_NO_MULTI:
175125930707SCorey Minyard if (ssif_info->max_xmit_msg_size > 32)
175225930707SCorey Minyard ssif_info->max_xmit_msg_size = 32;
175325930707SCorey Minyard if (ssif_info->max_recv_msg_size > 32)
175425930707SCorey Minyard ssif_info->max_recv_msg_size = 32;
175525930707SCorey Minyard break;
175625930707SCorey Minyard
175725930707SCorey Minyard case SSIF_MULTI_2_PART:
17583d69d43bSCorey Minyard if (ssif_info->max_xmit_msg_size > 63)
17593d69d43bSCorey Minyard ssif_info->max_xmit_msg_size = 63;
176025930707SCorey Minyard if (ssif_info->max_recv_msg_size > 62)
176125930707SCorey Minyard ssif_info->max_recv_msg_size = 62;
176225930707SCorey Minyard break;
176325930707SCorey Minyard
176425930707SCorey Minyard case SSIF_MULTI_n_PART:
176510042504SCorey Minyard /* We take whatever size given, but do some testing. */
176625930707SCorey Minyard break;
176725930707SCorey Minyard
176825930707SCorey Minyard default:
176925930707SCorey Minyard /* Data is not sane, just give up. */
177025930707SCorey Minyard goto no_support;
177125930707SCorey Minyard }
177225930707SCorey Minyard } else {
177325930707SCorey Minyard no_support:
177425930707SCorey Minyard /* Assume no multi-part or PEC support */
177583af4194SCorey Minyard dev_info(&ssif_info->client->dev,
177683af4194SCorey Minyard "Error fetching SSIF: %d %d %2.2x, your system probably doesn't support this command so using defaults\n",
177725930707SCorey Minyard rv, len, resp[2]);
177825930707SCorey Minyard
177925930707SCorey Minyard ssif_info->max_xmit_msg_size = 32;
178025930707SCorey Minyard ssif_info->max_recv_msg_size = 32;
178125930707SCorey Minyard ssif_info->multi_support = SSIF_NO_MULTI;
178225930707SCorey Minyard ssif_info->supports_pec = 0;
178325930707SCorey Minyard }
178425930707SCorey Minyard
178510042504SCorey Minyard test_multipart_messages(client, ssif_info, resp);
178610042504SCorey Minyard
178725930707SCorey Minyard /* Make sure the NMI timeout is cleared. */
178825930707SCorey Minyard msg[0] = IPMI_NETFN_APP_REQUEST << 2;
178925930707SCorey Minyard msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
179025930707SCorey Minyard msg[2] = WDT_PRE_TIMEOUT_INT;
179125930707SCorey Minyard rv = do_cmd(client, 3, msg, &len, resp);
179225930707SCorey Minyard if (rv || (len < 3) || (resp[2] != 0))
179383af4194SCorey Minyard dev_warn(&ssif_info->client->dev,
179483af4194SCorey Minyard "Unable to clear message flags: %d %d %2.2x\n",
179525930707SCorey Minyard rv, len, resp[2]);
179625930707SCorey Minyard
179725930707SCorey Minyard /* Attempt to enable the event buffer. */
179825930707SCorey Minyard msg[0] = IPMI_NETFN_APP_REQUEST << 2;
179925930707SCorey Minyard msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
180025930707SCorey Minyard rv = do_cmd(client, 2, msg, &len, resp);
180125930707SCorey Minyard if (rv || (len < 4) || (resp[2] != 0)) {
180283af4194SCorey Minyard dev_warn(&ssif_info->client->dev,
180383af4194SCorey Minyard "Error getting global enables: %d %d %2.2x\n",
180425930707SCorey Minyard rv, len, resp[2]);
180525930707SCorey Minyard rv = 0; /* Not fatal */
180625930707SCorey Minyard goto found;
180725930707SCorey Minyard }
180825930707SCorey Minyard
180991620521SCorey Minyard ssif_info->global_enables = resp[3];
181091620521SCorey Minyard
181125930707SCorey Minyard if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) {
181225930707SCorey Minyard ssif_info->has_event_buffer = true;
181325930707SCorey Minyard /* buffer is already enabled, nothing to do. */
181425930707SCorey Minyard goto found;
181525930707SCorey Minyard }
181625930707SCorey Minyard
181725930707SCorey Minyard msg[0] = IPMI_NETFN_APP_REQUEST << 2;
181825930707SCorey Minyard msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
181991620521SCorey Minyard msg[2] = ssif_info->global_enables | IPMI_BMC_EVT_MSG_BUFF;
182025930707SCorey Minyard rv = do_cmd(client, 3, msg, &len, resp);
182125930707SCorey Minyard if (rv || (len < 2)) {
182283af4194SCorey Minyard dev_warn(&ssif_info->client->dev,
182383af4194SCorey Minyard "Error setting global enables: %d %d %2.2x\n",
182425930707SCorey Minyard rv, len, resp[2]);
182525930707SCorey Minyard rv = 0; /* Not fatal */
182625930707SCorey Minyard goto found;
182725930707SCorey Minyard }
182825930707SCorey Minyard
182991620521SCorey Minyard if (resp[2] == 0) {
183025930707SCorey Minyard /* A successful return means the event buffer is supported. */
183125930707SCorey Minyard ssif_info->has_event_buffer = true;
183291620521SCorey Minyard ssif_info->global_enables |= IPMI_BMC_EVT_MSG_BUFF;
183391620521SCorey Minyard }
183491620521SCorey Minyard
1835bf2d0877SCorey Minyard /* Some systems don't behave well if you enable alerts. */
1836bf2d0877SCorey Minyard if (alerts_broken)
1837bf2d0877SCorey Minyard goto found;
1838bf2d0877SCorey Minyard
183991620521SCorey Minyard msg[0] = IPMI_NETFN_APP_REQUEST << 2;
184091620521SCorey Minyard msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
184191620521SCorey Minyard msg[2] = ssif_info->global_enables | IPMI_BMC_RCV_MSG_INTR;
184291620521SCorey Minyard rv = do_cmd(client, 3, msg, &len, resp);
184391620521SCorey Minyard if (rv || (len < 2)) {
184483af4194SCorey Minyard dev_warn(&ssif_info->client->dev,
184583af4194SCorey Minyard "Error setting global enables: %d %d %2.2x\n",
184691620521SCorey Minyard rv, len, resp[2]);
184791620521SCorey Minyard rv = 0; /* Not fatal */
184891620521SCorey Minyard goto found;
184991620521SCorey Minyard }
185091620521SCorey Minyard
185191620521SCorey Minyard if (resp[2] == 0) {
185291620521SCorey Minyard /* A successful return means the alert is supported. */
185391620521SCorey Minyard ssif_info->supports_alert = true;
185491620521SCorey Minyard ssif_info->global_enables |= IPMI_BMC_RCV_MSG_INTR;
185591620521SCorey Minyard }
185625930707SCorey Minyard
185725930707SCorey Minyard found:
185825930707SCorey Minyard if (ssif_dbg_probe) {
185983af4194SCorey Minyard dev_dbg(&ssif_info->client->dev,
186083af4194SCorey Minyard "%s: i2c_probe found device at i2c address %x\n",
186183af4194SCorey Minyard __func__, client->addr);
186225930707SCorey Minyard }
186325930707SCorey Minyard
186425930707SCorey Minyard spin_lock_init(&ssif_info->lock);
18658230831cSCorey Minyard ssif_info->ssif_state = SSIF_IDLE;
1866e99e88a9SKees Cook timer_setup(&ssif_info->retry_timer, retry_timeout, 0);
1867a1466ec5SCorey Minyard timer_setup(&ssif_info->watch_timer, watch_timeout, 0);
186825930707SCorey Minyard
186925930707SCorey Minyard for (i = 0; i < SSIF_NUM_STATS; i++)
187025930707SCorey Minyard atomic_set(&ssif_info->stats[i], 0);
187125930707SCorey Minyard
187225930707SCorey Minyard if (ssif_info->supports_pec)
187325930707SCorey Minyard ssif_info->client->flags |= I2C_CLIENT_PEC;
187425930707SCorey Minyard
187525930707SCorey Minyard ssif_info->handlers.owner = THIS_MODULE;
187625930707SCorey Minyard ssif_info->handlers.start_processing = ssif_start_processing;
1877a313dec6SCorey Minyard ssif_info->handlers.shutdown = shutdown_ssif;
187825930707SCorey Minyard ssif_info->handlers.get_smi_info = get_smi_info;
187925930707SCorey Minyard ssif_info->handlers.sender = sender;
188025930707SCorey Minyard ssif_info->handlers.request_events = request_events;
1881a1466ec5SCorey Minyard ssif_info->handlers.set_need_watch = ssif_set_need_watch;
188225930707SCorey Minyard
188325930707SCorey Minyard {
188425930707SCorey Minyard unsigned int thread_num;
188525930707SCorey Minyard
1886be8647d2SCorey Minyard thread_num = ((i2c_adapter_id(ssif_info->client->adapter)
1887be8647d2SCorey Minyard << 8) |
188825930707SCorey Minyard ssif_info->client->addr);
188925930707SCorey Minyard init_completion(&ssif_info->wake_thread);
189025930707SCorey Minyard ssif_info->thread = kthread_run(ipmi_ssif_thread, ssif_info,
189125930707SCorey Minyard "kssif%4.4x", thread_num);
189225930707SCorey Minyard if (IS_ERR(ssif_info->thread)) {
189325930707SCorey Minyard rv = PTR_ERR(ssif_info->thread);
189425930707SCorey Minyard dev_notice(&ssif_info->client->dev,
189525930707SCorey Minyard "Could not start kernel thread: error %d\n",
189625930707SCorey Minyard rv);
189725930707SCorey Minyard goto out;
189825930707SCorey Minyard }
189925930707SCorey Minyard }
190025930707SCorey Minyard
1901ac2673d5SCorey Minyard dev_set_drvdata(&ssif_info->client->dev, ssif_info);
1902ac2673d5SCorey Minyard rv = device_add_group(&ssif_info->client->dev,
1903ac2673d5SCorey Minyard &ipmi_ssif_dev_attr_group);
1904ac2673d5SCorey Minyard if (rv) {
1905ac2673d5SCorey Minyard dev_err(&ssif_info->client->dev,
1906ac2673d5SCorey Minyard "Unable to add device attributes: error %d\n",
1907ac2673d5SCorey Minyard rv);
1908ac2673d5SCorey Minyard goto out;
1909ac2673d5SCorey Minyard }
1910ac2673d5SCorey Minyard
191125930707SCorey Minyard rv = ipmi_register_smi(&ssif_info->handlers,
191225930707SCorey Minyard ssif_info,
191325930707SCorey Minyard &ssif_info->client->dev,
191425930707SCorey Minyard slave_addr);
191525930707SCorey Minyard if (rv) {
191683af4194SCorey Minyard dev_err(&ssif_info->client->dev,
191783af4194SCorey Minyard "Unable to register device: error %d\n", rv);
1918ac2673d5SCorey Minyard goto out_remove_attr;
191925930707SCorey Minyard }
192025930707SCorey Minyard
192125930707SCorey Minyard out:
19220944d889SCorey Minyard if (rv) {
1923a8627cdaSGustavo A. R. Silva if (addr_info)
19240745dde6SCorey Minyard addr_info->client = NULL;
1925a8627cdaSGustavo A. R. Silva
192683af4194SCorey Minyard dev_err(&ssif_info->client->dev,
192783af4194SCorey Minyard "Unable to start IPMI SSIF: %d\n", rv);
192834f35f8fSMian Yousaf Kaukab i2c_set_clientdata(client, NULL);
192925930707SCorey Minyard kfree(ssif_info);
19300944d889SCorey Minyard }
193125930707SCorey Minyard kfree(resp);
1932c4436c91SKamlakant Patel mutex_unlock(&ssif_infos_mutex);
193325930707SCorey Minyard return rv;
193425930707SCorey Minyard
1935ac2673d5SCorey Minyard out_remove_attr:
1936ac2673d5SCorey Minyard device_remove_group(&ssif_info->client->dev, &ipmi_ssif_dev_attr_group);
1937ac2673d5SCorey Minyard dev_set_drvdata(&ssif_info->client->dev, NULL);
193825930707SCorey Minyard goto out;
193925930707SCorey Minyard }
194025930707SCorey Minyard
new_ssif_client(int addr,char * adapter_name,int debug,int slave_addr,enum ipmi_addr_src addr_src,struct device * dev)194125930707SCorey Minyard static int new_ssif_client(int addr, char *adapter_name,
194225930707SCorey Minyard int debug, int slave_addr,
19430944d889SCorey Minyard enum ipmi_addr_src addr_src,
19440944d889SCorey Minyard struct device *dev)
194525930707SCorey Minyard {
194625930707SCorey Minyard struct ssif_addr_info *addr_info;
194725930707SCorey Minyard int rv = 0;
194825930707SCorey Minyard
194925930707SCorey Minyard mutex_lock(&ssif_infos_mutex);
195025930707SCorey Minyard if (ssif_info_find(addr, adapter_name, false)) {
195125930707SCorey Minyard rv = -EEXIST;
195225930707SCorey Minyard goto out_unlock;
195325930707SCorey Minyard }
195425930707SCorey Minyard
195525930707SCorey Minyard addr_info = kzalloc(sizeof(*addr_info), GFP_KERNEL);
195625930707SCorey Minyard if (!addr_info) {
195725930707SCorey Minyard rv = -ENOMEM;
195825930707SCorey Minyard goto out_unlock;
195925930707SCorey Minyard }
196025930707SCorey Minyard
196125930707SCorey Minyard if (adapter_name) {
196225930707SCorey Minyard addr_info->adapter_name = kstrdup(adapter_name, GFP_KERNEL);
196325930707SCorey Minyard if (!addr_info->adapter_name) {
196425930707SCorey Minyard kfree(addr_info);
196525930707SCorey Minyard rv = -ENOMEM;
196625930707SCorey Minyard goto out_unlock;
196725930707SCorey Minyard }
196825930707SCorey Minyard }
196925930707SCorey Minyard
1970b00839caSJustin Stitt strscpy(addr_info->binfo.type, DEVICE_NAME,
197125930707SCorey Minyard sizeof(addr_info->binfo.type));
197225930707SCorey Minyard addr_info->binfo.addr = addr;
197325930707SCorey Minyard addr_info->binfo.platform_data = addr_info;
197425930707SCorey Minyard addr_info->debug = debug;
197525930707SCorey Minyard addr_info->slave_addr = slave_addr;
197625930707SCorey Minyard addr_info->addr_src = addr_src;
19770944d889SCorey Minyard addr_info->dev = dev;
19780944d889SCorey Minyard
197987ff091cSCorey Minyard if (dev)
19800944d889SCorey Minyard dev_set_drvdata(dev, addr_info);
198125930707SCorey Minyard
198225930707SCorey Minyard list_add_tail(&addr_info->link, &ssif_infos);
198325930707SCorey Minyard
19842a556ce7SCorey Minyard /* Address list will get it */
198525930707SCorey Minyard
198625930707SCorey Minyard out_unlock:
198725930707SCorey Minyard mutex_unlock(&ssif_infos_mutex);
198825930707SCorey Minyard return rv;
198925930707SCorey Minyard }
199025930707SCorey Minyard
free_ssif_clients(void)199125930707SCorey Minyard static void free_ssif_clients(void)
199225930707SCorey Minyard {
199325930707SCorey Minyard struct ssif_addr_info *info, *tmp;
199425930707SCorey Minyard
199525930707SCorey Minyard mutex_lock(&ssif_infos_mutex);
199625930707SCorey Minyard list_for_each_entry_safe(info, tmp, &ssif_infos, link) {
199725930707SCorey Minyard list_del(&info->link);
199825930707SCorey Minyard kfree(info->adapter_name);
199925930707SCorey Minyard kfree(info);
200025930707SCorey Minyard }
200125930707SCorey Minyard mutex_unlock(&ssif_infos_mutex);
200225930707SCorey Minyard }
200325930707SCorey Minyard
ssif_address_list(void)200425930707SCorey Minyard static unsigned short *ssif_address_list(void)
200525930707SCorey Minyard {
200625930707SCorey Minyard struct ssif_addr_info *info;
2007c75c5075SCorey Minyard unsigned int count = 0, i = 0;
200825930707SCorey Minyard unsigned short *address_list;
200925930707SCorey Minyard
201025930707SCorey Minyard list_for_each_entry(info, &ssif_infos, link)
201125930707SCorey Minyard count++;
201225930707SCorey Minyard
20136396bb22SKees Cook address_list = kcalloc(count + 1, sizeof(*address_list),
20146396bb22SKees Cook GFP_KERNEL);
201525930707SCorey Minyard if (!address_list)
201625930707SCorey Minyard return NULL;
201725930707SCorey Minyard
201825930707SCorey Minyard list_for_each_entry(info, &ssif_infos, link) {
201925930707SCorey Minyard unsigned short addr = info->binfo.addr;
202025930707SCorey Minyard int j;
202125930707SCorey Minyard
202225930707SCorey Minyard for (j = 0; j < i; j++) {
202325930707SCorey Minyard if (address_list[j] == addr)
2024c75c5075SCorey Minyard /* Found a dup. */
2025c75c5075SCorey Minyard break;
202625930707SCorey Minyard }
2027c75c5075SCorey Minyard if (j == i) /* Didn't find it in the list. */
2028c75c5075SCorey Minyard address_list[i++] = addr;
202925930707SCorey Minyard }
203025930707SCorey Minyard address_list[i] = I2C_CLIENT_END;
203125930707SCorey Minyard
203225930707SCorey Minyard return address_list;
203325930707SCorey Minyard }
203425930707SCorey Minyard
203525930707SCorey Minyard #ifdef CONFIG_ACPI
20365186cf9cSMathias Krause static const struct acpi_device_id ssif_acpi_match[] = {
203725930707SCorey Minyard { "IPI0001", 0 },
203825930707SCorey Minyard { },
203925930707SCorey Minyard };
204025930707SCorey Minyard MODULE_DEVICE_TABLE(acpi, ssif_acpi_match);
204125930707SCorey Minyard #endif
204225930707SCorey Minyard
204325930707SCorey Minyard #ifdef CONFIG_DMI
dmi_ipmi_probe(struct platform_device * pdev)20440944d889SCorey Minyard static int dmi_ipmi_probe(struct platform_device *pdev)
204525930707SCorey Minyard {
204695e300c0SCorey Minyard u8 slave_addr = 0;
20470944d889SCorey Minyard u16 i2c_addr;
20480944d889SCorey Minyard int rv;
204925930707SCorey Minyard
20500944d889SCorey Minyard if (!ssif_trydmi)
20510944d889SCorey Minyard return -ENODEV;
205225930707SCorey Minyard
20530944d889SCorey Minyard rv = device_property_read_u16(&pdev->dev, "i2c-addr", &i2c_addr);
20540944d889SCorey Minyard if (rv) {
205525880f7dSJoe Perches dev_warn(&pdev->dev, "No i2c-addr property\n");
20560944d889SCorey Minyard return -ENODEV;
205725930707SCorey Minyard }
205825930707SCorey Minyard
20590944d889SCorey Minyard rv = device_property_read_u8(&pdev->dev, "slave-addr", &slave_addr);
20600944d889SCorey Minyard if (rv)
2061ed6c3a6dSCorey Minyard slave_addr = 0x20;
206225930707SCorey Minyard
20630944d889SCorey Minyard return new_ssif_client(i2c_addr, NULL, 0,
20640944d889SCorey Minyard slave_addr, SI_SMBIOS, &pdev->dev);
206525930707SCorey Minyard }
206625930707SCorey Minyard #else
dmi_ipmi_probe(struct platform_device * pdev)20670944d889SCorey Minyard static int dmi_ipmi_probe(struct platform_device *pdev)
20680944d889SCorey Minyard {
20690944d889SCorey Minyard return -ENODEV;
20700944d889SCorey Minyard }
207125930707SCorey Minyard #endif
207225930707SCorey Minyard
207325930707SCorey Minyard static const struct i2c_device_id ssif_id[] = {
207419a01155SUwe Kleine-König { DEVICE_NAME },
207525930707SCorey Minyard { }
207625930707SCorey Minyard };
207725930707SCorey Minyard MODULE_DEVICE_TABLE(i2c, ssif_id);
207825930707SCorey Minyard
207925930707SCorey Minyard static struct i2c_driver ssif_i2c_driver = {
208025930707SCorey Minyard .class = I2C_CLASS_HWMON,
208125930707SCorey Minyard .driver = {
208225930707SCorey Minyard .name = DEVICE_NAME
208325930707SCorey Minyard },
2084e64c82b8SUwe Kleine-König .probe = ssif_probe,
208525930707SCorey Minyard .remove = ssif_remove,
208691620521SCorey Minyard .alert = ssif_alert,
208725930707SCorey Minyard .id_table = ssif_id,
208825930707SCorey Minyard .detect = ssif_detect
208925930707SCorey Minyard };
209025930707SCorey Minyard
ssif_platform_probe(struct platform_device * dev)20910944d889SCorey Minyard static int ssif_platform_probe(struct platform_device *dev)
20920944d889SCorey Minyard {
20930944d889SCorey Minyard return dmi_ipmi_probe(dev);
20940944d889SCorey Minyard }
20950944d889SCorey Minyard
ssif_platform_remove(struct platform_device * dev)2096a69da502SUwe Kleine-König static void ssif_platform_remove(struct platform_device *dev)
20970944d889SCorey Minyard {
20980944d889SCorey Minyard struct ssif_addr_info *addr_info = dev_get_drvdata(&dev->dev);
20990944d889SCorey Minyard
21000944d889SCorey Minyard mutex_lock(&ssif_infos_mutex);
21010944d889SCorey Minyard list_del(&addr_info->link);
21020944d889SCorey Minyard kfree(addr_info);
21030944d889SCorey Minyard mutex_unlock(&ssif_infos_mutex);
21040944d889SCorey Minyard }
21050944d889SCorey Minyard
2106b3096c70SCorey Minyard static const struct platform_device_id ssif_plat_ids[] = {
2107b3096c70SCorey Minyard { "dmi-ipmi-ssif", 0 },
2108b3096c70SCorey Minyard { }
2109b3096c70SCorey Minyard };
21100e38f7ecSYuntao Liu MODULE_DEVICE_TABLE(platform, ssif_plat_ids);
2111b3096c70SCorey Minyard
21120944d889SCorey Minyard static struct platform_driver ipmi_driver = {
21130944d889SCorey Minyard .driver = {
21140944d889SCorey Minyard .name = DEVICE_NAME,
21150944d889SCorey Minyard },
21160944d889SCorey Minyard .probe = ssif_platform_probe,
2117a69da502SUwe Kleine-König .remove_new = ssif_platform_remove,
2118b3096c70SCorey Minyard .id_table = ssif_plat_ids
21190944d889SCorey Minyard };
21200944d889SCorey Minyard
init_ipmi_ssif(void)2121ec7174f6SXiu Jianfeng static int __init init_ipmi_ssif(void)
212225930707SCorey Minyard {
212325930707SCorey Minyard int i;
212425930707SCorey Minyard int rv;
212525930707SCorey Minyard
212625930707SCorey Minyard if (initialized)
212725930707SCorey Minyard return 0;
212825930707SCorey Minyard
212925930707SCorey Minyard pr_info("IPMI SSIF Interface driver\n");
213025930707SCorey Minyard
213125930707SCorey Minyard /* build list for i2c from addr list */
213225930707SCorey Minyard for (i = 0; i < num_addrs; i++) {
213325930707SCorey Minyard rv = new_ssif_client(addr[i], adapter_name[i],
213425930707SCorey Minyard dbg[i], slave_addrs[i],
21350944d889SCorey Minyard SI_HARDCODED, NULL);
2136d467f7a4SCorey Minyard if (rv)
213725880f7dSJoe Perches pr_err("Couldn't add hardcoded device at addr 0x%x\n",
213825930707SCorey Minyard addr[i]);
213925930707SCorey Minyard }
214025930707SCorey Minyard
214125930707SCorey Minyard if (ssif_tryacpi)
214225930707SCorey Minyard ssif_i2c_driver.driver.acpi_match_table =
214325930707SCorey Minyard ACPI_PTR(ssif_acpi_match);
21440944d889SCorey Minyard
21450944d889SCorey Minyard if (ssif_trydmi) {
21460944d889SCorey Minyard rv = platform_driver_register(&ipmi_driver);
21470944d889SCorey Minyard if (rv)
214825880f7dSJoe Perches pr_err("Unable to register driver: %d\n", rv);
21492cd0e544SKefeng Wang else
21502cd0e544SKefeng Wang platform_registered = true;
21510944d889SCorey Minyard }
21520944d889SCorey Minyard
215325930707SCorey Minyard ssif_i2c_driver.address_list = ssif_address_list();
215425930707SCorey Minyard
215525930707SCorey Minyard rv = i2c_add_driver(&ssif_i2c_driver);
215625930707SCorey Minyard if (!rv)
215725930707SCorey Minyard initialized = true;
215825930707SCorey Minyard
215925930707SCorey Minyard return rv;
216025930707SCorey Minyard }
216125930707SCorey Minyard module_init(init_ipmi_ssif);
216225930707SCorey Minyard
cleanup_ipmi_ssif(void)2163ec7174f6SXiu Jianfeng static void __exit cleanup_ipmi_ssif(void)
216425930707SCorey Minyard {
216525930707SCorey Minyard if (!initialized)
216625930707SCorey Minyard return;
216725930707SCorey Minyard
216825930707SCorey Minyard initialized = false;
216925930707SCorey Minyard
217025930707SCorey Minyard i2c_del_driver(&ssif_i2c_driver);
217125930707SCorey Minyard
217236e398d7SCorey Minyard kfree(ssif_i2c_driver.address_list);
217336e398d7SCorey Minyard
21742cd0e544SKefeng Wang if (ssif_trydmi && platform_registered)
21750944d889SCorey Minyard platform_driver_unregister(&ipmi_driver);
21760944d889SCorey Minyard
217725930707SCorey Minyard free_ssif_clients();
217825930707SCorey Minyard }
217925930707SCorey Minyard module_exit(cleanup_ipmi_ssif);
218025930707SCorey Minyard
21810944d889SCorey Minyard MODULE_ALIAS("platform:dmi-ipmi-ssif");
218225930707SCorey Minyard MODULE_AUTHOR("Todd C Davis <todd.c.davis@intel.com>, Corey Minyard <minyard@acm.org>");
218325930707SCorey Minyard MODULE_DESCRIPTION("IPMI driver for management controllers on a SMBus");
218425930707SCorey Minyard MODULE_LICENSE("GPL");
2185