Commit 6e4dc3d5 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-5.10-1' of git://github.com/cminyard/linux-ipmi

Pull IPMI updates from Corey Minyard:
 "Some minor bug fixes, return values, cleanups of prints, conversion of
  tasklets to the new API.

  The biggest change is retrying the initial information fetch from the
  management controller. If that fails, the iterface is not operational,
  and one group was having trouble with the management controller not
  being ready when the OS started up. So a retry was added"

* tag 'for-linus-5.10-1' of git://github.com/cminyard/linux-ipmi:
  ipmi_si: Fix wrong return value in try_smi_init()
  ipmi: msghandler: Fix a signedness bug
  ipmi: add retry in try_get_dev_id()
  ipmi: Clean up some printks
  ipmi:msghandler: retry to get device id on an error
  ipmi:sm: Print current state when the state is invalid
  ipmi: Reset response handler when failing to send the command
  ipmi: add a newline when printing parameter 'panic_op' by sysfs
  char: ipmi: convert tasklets to use new tasklet_setup() API
parents 2f6c6d08 8fe7990c
......@@ -213,8 +213,10 @@ static int bt_start_transaction(struct si_sm_data *bt,
if (bt->state == BT_STATE_LONG_BUSY)
return IPMI_NODE_BUSY_ERR;
if (bt->state != BT_STATE_IDLE)
if (bt->state != BT_STATE_IDLE) {
dev_warn(bt->io->dev, "BT in invalid state %d\n", bt->state);
return IPMI_NOT_IN_MY_STATE_ERR;
}
if (bt_debug & BT_DEBUG_MSG) {
dev_dbg(bt->io->dev, "+++++++++++++++++ New command\n");
......
......@@ -17,6 +17,8 @@
* that document.
*/
#define DEBUG /* So dev_dbg() is always available. */
#include <linux/kernel.h> /* For printk. */
#include <linux/module.h>
#include <linux/moduleparam.h>
......@@ -187,8 +189,8 @@ static inline void start_error_recovery(struct si_sm_data *kcs, char *reason)
(kcs->error_retries)++;
if (kcs->error_retries > MAX_ERROR_RETRIES) {
if (kcs_debug & KCS_DEBUG_ENABLE)
printk(KERN_DEBUG "ipmi_kcs_sm: kcs hosed: %s\n",
reason);
dev_dbg(kcs->io->dev, "ipmi_kcs_sm: kcs hosed: %s\n",
reason);
kcs->state = KCS_HOSED;
} else {
kcs->error0_timeout = jiffies + ERROR0_OBF_WAIT_JIFFIES;
......@@ -268,11 +270,13 @@ static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
if (size > MAX_KCS_WRITE_SIZE)
return IPMI_REQ_LEN_EXCEEDED_ERR;
if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED))
if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
dev_warn(kcs->io->dev, "KCS in invalid state %d\n", kcs->state);
return IPMI_NOT_IN_MY_STATE_ERR;
}
if (kcs_debug & KCS_DEBUG_MSG) {
printk(KERN_DEBUG "start_kcs_transaction -");
dev_dbg(kcs->io->dev, "%s -", __func__);
for (i = 0; i < size; i++)
pr_cont(" %02x", data[i]);
pr_cont("\n");
......@@ -331,7 +335,8 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
status = read_status(kcs);
if (kcs_debug & KCS_DEBUG_STATES)
printk(KERN_DEBUG "KCS: State = %d, %x\n", kcs->state, status);
dev_dbg(kcs->io->dev,
"KCS: State = %d, %x\n", kcs->state, status);
/* All states wait for ibf, so just do it here. */
if (!check_ibf(kcs, status, time))
......
......@@ -34,12 +34,13 @@
#include <linux/uuid.h>
#include <linux/nospec.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#define IPMI_DRIVER_VERSION "39.2"
static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void);
static int ipmi_init_msghandler(void);
static void smi_recv_tasklet(unsigned long);
static void smi_recv_tasklet(struct tasklet_struct *t);
static void handle_new_recv_msgs(struct ipmi_smi *intf);
static void need_waiter(struct ipmi_smi *intf);
static int handle_one_recv_msg(struct ipmi_smi *intf,
......@@ -60,6 +61,7 @@ enum ipmi_panic_event_op {
#else
#define IPMI_PANIC_DEFAULT IPMI_SEND_PANIC_EVENT_NONE
#endif
static enum ipmi_panic_event_op ipmi_send_panic_event = IPMI_PANIC_DEFAULT;
static int panic_op_write_handler(const char *val,
......@@ -89,19 +91,19 @@ static int panic_op_read_handler(char *buffer, const struct kernel_param *kp)
{
switch (ipmi_send_panic_event) {
case IPMI_SEND_PANIC_EVENT_NONE:
strcpy(buffer, "none");
strcpy(buffer, "none\n");
break;
case IPMI_SEND_PANIC_EVENT:
strcpy(buffer, "event");
strcpy(buffer, "event\n");
break;
case IPMI_SEND_PANIC_EVENT_STRING:
strcpy(buffer, "string");
strcpy(buffer, "string\n");
break;
default:
strcpy(buffer, "???");
strcpy(buffer, "???\n");
break;
}
......@@ -317,6 +319,7 @@ struct bmc_device {
int dyn_guid_set;
struct kref usecount;
struct work_struct remove_work;
unsigned char cc; /* completion code */
};
#define to_bmc_device(x) container_of((x), struct bmc_device, pdev.dev)
......@@ -2381,6 +2384,8 @@ static void bmc_device_id_handler(struct ipmi_smi *intf,
msg->msg.data, msg->msg.data_len, &intf->bmc->fetch_id);
if (rv) {
dev_warn(intf->si_dev, "device id demangle failed: %d\n", rv);
/* record completion code when error */
intf->bmc->cc = msg->msg.data[0];
intf->bmc->dyn_id_set = 0;
} else {
/*
......@@ -2426,23 +2431,39 @@ send_get_device_id_cmd(struct ipmi_smi *intf)
static int __get_device_id(struct ipmi_smi *intf, struct bmc_device *bmc)
{
int rv;
bmc->dyn_id_set = 2;
unsigned int retry_count = 0;
intf->null_user_handler = bmc_device_id_handler;
retry:
bmc->cc = 0;
bmc->dyn_id_set = 2;
rv = send_get_device_id_cmd(intf);
if (rv)
return rv;
goto out_reset_handler;
wait_event(intf->waitq, bmc->dyn_id_set != 2);
if (!bmc->dyn_id_set)
if (!bmc->dyn_id_set) {
if ((bmc->cc == IPMI_DEVICE_IN_FW_UPDATE_ERR
|| bmc->cc == IPMI_DEVICE_IN_INIT_ERR
|| bmc->cc == IPMI_NOT_IN_MY_STATE_ERR)
&& ++retry_count <= GET_DEVICE_ID_MAX_RETRY) {
msleep(500);
dev_warn(intf->si_dev,
"BMC returned 0x%2.2x, retry get bmc device id\n",
bmc->cc);
goto retry;
}
rv = -EIO; /* Something went wrong in the fetch. */
}
/* dyn_id_set makes the id data available. */
smp_rmb();
out_reset_handler:
intf->null_user_handler = NULL;
return rv;
......@@ -3245,7 +3266,6 @@ channel_handler(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
/* It's the one we want */
if (msg->msg.data[0] != 0) {
/* Got an error from the channel, just go on. */
if (msg->msg.data[0] == IPMI_INVALID_COMMAND_ERR) {
/*
* If the MC does not support this
......@@ -3329,6 +3349,7 @@ static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id)
dev_warn(intf->si_dev,
"Error sending channel information for channel 0, %d\n",
rv);
intf->null_user_handler = NULL;
return -EIO;
}
......@@ -3430,9 +3451,8 @@ int ipmi_add_smi(struct module *owner,
intf->curr_seq = 0;
spin_lock_init(&intf->waiting_rcv_msgs_lock);
INIT_LIST_HEAD(&intf->waiting_rcv_msgs);
tasklet_init(&intf->recv_tasklet,
smi_recv_tasklet,
(unsigned long) intf);
tasklet_setup(&intf->recv_tasklet,
smi_recv_tasklet);
atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0);
spin_lock_init(&intf->xmit_msgs_lock);
INIT_LIST_HEAD(&intf->xmit_msgs);
......@@ -4467,10 +4487,10 @@ static void handle_new_recv_msgs(struct ipmi_smi *intf)
}
}
static void smi_recv_tasklet(unsigned long val)
static void smi_recv_tasklet(struct tasklet_struct *t)
{
unsigned long flags = 0; /* keep us warning-free. */
struct ipmi_smi *intf = (struct ipmi_smi *) val;
struct ipmi_smi *intf = from_tasklet(intf, t, recv_tasklet);
int run_to_completion = intf->run_to_completion;
struct ipmi_smi_msg *newmsg = NULL;
......@@ -4542,7 +4562,7 @@ void ipmi_smi_msg_received(struct ipmi_smi *intf,
spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
if (run_to_completion)
smi_recv_tasklet((unsigned long) intf);
smi_recv_tasklet(&intf->recv_tasklet);
else
tasklet_schedule(&intf->recv_tasklet);
}
......
......@@ -1316,6 +1316,7 @@ static int try_get_dev_id(struct smi_info *smi_info)
unsigned char *resp;
unsigned long resp_len;
int rv = 0;
unsigned int retry_count = 0;
resp = kmalloc(IPMI_MAX_MSG_LENGTH, GFP_KERNEL);
if (!resp)
......@@ -1327,6 +1328,8 @@ static int try_get_dev_id(struct smi_info *smi_info)
*/
msg[0] = IPMI_NETFN_APP_REQUEST << 2;
msg[1] = IPMI_GET_DEVICE_ID_CMD;
retry:
smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
rv = wait_for_msg_done(smi_info);
......@@ -1339,6 +1342,20 @@ static int try_get_dev_id(struct smi_info *smi_info)
/* Check and record info from the get device id, in case we need it. */
rv = ipmi_demangle_device_id(resp[0] >> 2, resp[1],
resp + 2, resp_len - 2, &smi_info->device_id);
if (rv) {
/* record completion code */
unsigned char cc = *(resp + 2);
if ((cc == IPMI_DEVICE_IN_FW_UPDATE_ERR
|| cc == IPMI_DEVICE_IN_INIT_ERR
|| cc == IPMI_NOT_IN_MY_STATE_ERR)
&& ++retry_count <= GET_DEVICE_ID_MAX_RETRY) {
dev_warn(smi_info->io.dev,
"BMC returned 0x%2.2x, retry get bmc device id\n",
cc);
goto retry;
}
}
out:
kfree(resp);
......@@ -1963,7 +1980,7 @@ static int try_smi_init(struct smi_info *new_smi)
/* Do this early so it's available for logs. */
if (!new_smi->io.dev) {
pr_err("IPMI interface added with no device\n");
rv = EIO;
rv = -EIO;
goto out_err;
}
......
......@@ -21,6 +21,8 @@
* 2001 Hewlett-Packard Company
*/
#define DEBUG /* So dev_dbg() is always available. */
#include <linux/kernel.h> /* For printk. */
#include <linux/string.h>
#include <linux/module.h>
......@@ -126,11 +128,14 @@ static int start_smic_transaction(struct si_sm_data *smic,
if (size > MAX_SMIC_WRITE_SIZE)
return IPMI_REQ_LEN_EXCEEDED_ERR;
if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED))
if ((smic->state != SMIC_IDLE) && (smic->state != SMIC_HOSED)) {
dev_warn(smic->io->dev,
"SMIC in invalid state %d\n", smic->state);
return IPMI_NOT_IN_MY_STATE_ERR;
}
if (smic_debug & SMIC_DEBUG_MSG) {
printk(KERN_DEBUG "start_smic_transaction -");
dev_dbg(smic->io->dev, "%s -", __func__);
for (i = 0; i < size; i++)
pr_cont(" %02x", data[i]);
pr_cont("\n");
......@@ -152,7 +157,7 @@ static int smic_get_result(struct si_sm_data *smic,
int i;
if (smic_debug & SMIC_DEBUG_MSG) {
printk(KERN_DEBUG "smic_get result -");
dev_dbg(smic->io->dev, "smic_get result -");
for (i = 0; i < smic->read_pos; i++)
pr_cont(" %02x", smic->read_data[i]);
pr_cont("\n");
......@@ -324,9 +329,9 @@ static enum si_sm_result smic_event(struct si_sm_data *smic, long time)
}
if (smic->state != SMIC_IDLE) {
if (smic_debug & SMIC_DEBUG_STATES)
printk(KERN_DEBUG
"smic_event - smic->smic_timeout = %ld, time = %ld\n",
smic->smic_timeout, time);
dev_dbg(smic->io->dev,
"%s - smic->smic_timeout = %ld, time = %ld\n",
__func__, smic->smic_timeout, time);
/*
* FIXME: smic_event is sometimes called with time >
* SMIC_RETRY_TIMEOUT
......@@ -345,8 +350,9 @@ static enum si_sm_result smic_event(struct si_sm_data *smic, long time)
status = read_smic_status(smic);
if (smic_debug & SMIC_DEBUG_STATES)
printk(KERN_DEBUG "smic_event - state = %d, flags = 0x%02x, status = 0x%02x\n",
smic->state, flags, status);
dev_dbg(smic->io->dev,
"%s - state = %d, flags = 0x%02x, status = 0x%02x\n",
__func__, smic->state, flags, status);
switch (smic->state) {
case SMIC_IDLE:
......@@ -436,8 +442,9 @@ static enum si_sm_result smic_event(struct si_sm_data *smic, long time)
data = read_smic_data(smic);
if (data != 0) {
if (smic_debug & SMIC_DEBUG_ENABLE)
printk(KERN_DEBUG "SMIC_WRITE_END: data = %02x\n",
data);
dev_dbg(smic->io->dev,
"SMIC_WRITE_END: data = %02x\n",
data);
start_error_recovery(smic,
"state = SMIC_WRITE_END, "
"data != SUCCESS");
......@@ -516,8 +523,9 @@ static enum si_sm_result smic_event(struct si_sm_data *smic, long time)
/* data register holds an error code */
if (data != 0) {
if (smic_debug & SMIC_DEBUG_ENABLE)
printk(KERN_DEBUG "SMIC_READ_END: data = %02x\n",
data);
dev_dbg(smic->io->dev,
"SMIC_READ_END: data = %02x\n",
data);
start_error_recovery(smic,
"state = SMIC_READ_END, "
"data != SUCCESS");
......@@ -533,7 +541,8 @@ static enum si_sm_result smic_event(struct si_sm_data *smic, long time)
default:
if (smic_debug & SMIC_DEBUG_ENABLE) {
printk(KERN_DEBUG "smic->state = %d\n", smic->state);
dev_dbg(smic->io->dev,
"smic->state = %d\n", smic->state);
start_error_recovery(smic, "state = UNKNOWN");
return SI_SM_CALL_WITH_DELAY;
}
......
......@@ -333,4 +333,6 @@ struct ipmi_smi_info {
/* This is to get the private info of struct ipmi_smi */
extern int ipmi_get_smi_info(int if_num, struct ipmi_smi_info *data);
#define GET_DEVICE_ID_MAX_RETRY 5
#endif /* __LINUX_IPMI_H */
......@@ -69,6 +69,8 @@
#define IPMI_ERR_MSG_TRUNCATED 0xc6
#define IPMI_REQ_LEN_INVALID_ERR 0xc7
#define IPMI_REQ_LEN_EXCEEDED_ERR 0xc8
#define IPMI_DEVICE_IN_FW_UPDATE_ERR 0xd1
#define IPMI_DEVICE_IN_INIT_ERR 0xd2
#define IPMI_NOT_IN_MY_STATE_ERR 0xd5 /* IPMI 2.0 */
#define IPMI_LOST_ARBITRATION_ERR 0x81
#define IPMI_BUS_ERR 0x82
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment