Commit 90b12f42 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull IPMI updates from Corey Minyard:
 "This includes a number of small fixes, as usual.

  It also includes a new driver for doing the i2c (SSIF) interface
  BMC-side, pretty much completing the BMC side interfaces"

* tag 'for-linus-6.2-1' of https://github.com/cminyard/linux-ipmi:
  ipmi/watchdog: use strscpy() to instead of strncpy()
  ipmi: ssif_bmc: Convert to i2c's .probe_new()
  ipmi: fix use after free in _ipmi_destroy_user()
  ipmi/watchdog: Include <linux/kstrtox.h> when appropriate
  ipmi:ssif: Increase the message retry time
  ipmi: Fix some kernel-doc warnings
  ipmi: ssif_bmc: Use EPOLLIN instead of POLLIN
  ipmi: fix msg stack when IPMI is disconnected
  ipmi: fix memleak when unload ipmi driver
  ipmi: fix long wait in unload when IPMI disconnect
  ipmi: kcs: Poll OBF briefly to reduce OBE latency
  bindings: ipmi: Add binding for SSIF BMC driver
  ipmi: ssif_bmc: Add SSIF BMC driver
parents 2043f9a3 c6f613e5
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/ipmi/ssif-bmc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: SSIF IPMI BMC interface
description: SSIF IPMI BMC device bindings
maintainers:
- Quan Nguyen <quan@os.amperecomputing.com>
properties:
compatible:
enum:
- ssif-bmc
reg:
maxItems: 1
required:
- compatible
- reg
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
ssif-bmc@10 {
compatible = "ssif-bmc";
reg = <0x10>;
};
};
......@@ -169,6 +169,16 @@ config ASPEED_BT_IPMI_BMC
found on Aspeed SOCs (AST2400 and AST2500). The driver
implements the BMC side of the BT interface.
config SSIF_IPMI_BMC
tristate "SSIF IPMI BMC driver"
depends on I2C && I2C_SLAVE
help
This enables the IPMI SMBus system interface (SSIF) at the
management (BMC) side.
The driver implements the BMC side of the SMBus system
interface (SSIF).
config IPMB_DEVICE_INTERFACE
tristate 'IPMB Interface handler'
depends on I2C
......
......@@ -30,3 +30,4 @@ obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o
obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o
obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o
obj-$(CONFIG_IPMB_DEVICE_INTERFACE) += ipmb_dev_int.o
obj-$(CONFIG_SSIF_IPMI_BMC) += ssif_bmc.o
......@@ -122,10 +122,10 @@ struct si_sm_data {
unsigned long error0_timeout;
};
static unsigned int init_kcs_data(struct si_sm_data *kcs,
struct si_sm_io *io)
static unsigned int init_kcs_data_with_state(struct si_sm_data *kcs,
struct si_sm_io *io, enum kcs_states state)
{
kcs->state = KCS_IDLE;
kcs->state = state;
kcs->io = io;
kcs->write_pos = 0;
kcs->write_count = 0;
......@@ -140,6 +140,12 @@ static unsigned int init_kcs_data(struct si_sm_data *kcs,
return 2;
}
static unsigned int init_kcs_data(struct si_sm_data *kcs,
struct si_sm_io *io)
{
return init_kcs_data_with_state(kcs, io, KCS_IDLE);
}
static inline unsigned char read_status(struct si_sm_data *kcs)
{
return kcs->io->inputb(kcs->io, 1);
......@@ -270,7 +276,7 @@ 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) {
dev_warn(kcs->io->dev, "KCS in invalid state %d\n", kcs->state);
return IPMI_NOT_IN_MY_STATE_ERR;
}
......@@ -495,7 +501,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
}
if (kcs->state == KCS_HOSED) {
init_kcs_data(kcs, kcs->io);
init_kcs_data_with_state(kcs, kcs->io, KCS_ERROR0);
return SI_SM_HOSED;
}
......
......@@ -614,7 +614,7 @@ static int __ipmi_bmc_register(struct ipmi_smi *intf,
static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id);
/**
/*
* The driver model view of the IPMI messaging driver.
*/
static struct platform_driver ipmidriver = {
......@@ -1330,6 +1330,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
unsigned long flags;
struct cmd_rcvr *rcvr;
struct cmd_rcvr *rcvrs = NULL;
struct module *owner;
if (!acquire_ipmi_user(user, &i)) {
/*
......@@ -1392,8 +1393,9 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
kfree(rcvr);
}
owner = intf->owner;
kref_put(&intf->refcount, intf_free);
module_put(intf->owner);
module_put(owner);
}
int ipmi_destroy_user(struct ipmi_user *user)
......@@ -3704,12 +3706,16 @@ static void deliver_smi_err_response(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg,
unsigned char err)
{
int rv;
msg->rsp[0] = msg->data[0] | 4;
msg->rsp[1] = msg->data[1];
msg->rsp[2] = err;
msg->rsp_size = 3;
/* It's an error, so it will never requeue, no need to check return. */
handle_one_recv_msg(intf, msg);
/* This will never requeue, but it may ask us to free the message. */
rv = handle_one_recv_msg(intf, msg);
if (rv == 0)
ipmi_free_smi_msg(msg);
}
static void cleanup_smi_msgs(struct ipmi_smi *intf)
......
......@@ -2153,6 +2153,20 @@ static int __init init_ipmi_si(void)
}
module_init(init_ipmi_si);
static void wait_msg_processed(struct smi_info *smi_info)
{
unsigned long jiffies_now;
long time_diff;
while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
jiffies_now = jiffies;
time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
* SI_USEC_PER_JIFFY);
smi_event_handler(smi_info, time_diff);
schedule_timeout_uninterruptible(1);
}
}
static void shutdown_smi(void *send_info)
{
struct smi_info *smi_info = send_info;
......@@ -2187,16 +2201,13 @@ static void shutdown_smi(void *send_info)
* in the BMC. Note that timers and CPU interrupts are off,
* so no need for locks.
*/
while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
poll(smi_info);
schedule_timeout_uninterruptible(1);
}
wait_msg_processed(smi_info);
if (smi_info->handlers)
disable_si_irq(smi_info);
while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
poll(smi_info);
schedule_timeout_uninterruptible(1);
}
wait_msg_processed(smi_info);
if (smi_info->handlers)
smi_info->handlers->cleanup(smi_info->si_sm);
......
......@@ -74,7 +74,7 @@
/*
* Timer values
*/
#define SSIF_MSG_USEC 20000 /* 20ms between message tries. */
#define SSIF_MSG_USEC 60000 /* 60ms between message tries. */
#define SSIF_MSG_PART_USEC 5000 /* 5ms for a message part */
/* How many times to we retry sending/receiving the message. */
......
......@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/kdebug.h>
#include <linux/kstrtox.h>
#include <linux/rwsem.h>
#include <linux/errno.h>
#include <linux/uaccess.h>
......@@ -212,8 +213,7 @@ static int set_param_str(const char *val, const struct kernel_param *kp)
char valcp[16];
char *s;
strncpy(valcp, val, 15);
valcp[15] = '\0';
strscpy(valcp, val, 16);
s = strstrip(valcp);
......
......@@ -406,13 +406,31 @@ static void aspeed_kcs_check_obe(struct timer_list *timer)
static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state)
{
struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc);
int rc;
u8 str;
/* We don't have an OBE IRQ, emulate it */
if (mask & KCS_BMC_EVENT_TYPE_OBE) {
if (KCS_BMC_EVENT_TYPE_OBE & state)
mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD);
else
if (KCS_BMC_EVENT_TYPE_OBE & state) {
/*
* Given we don't have an OBE IRQ, delay by polling briefly to see if we can
* observe such an event before returning to the caller. This is not
* incorrect because OBF may have already become clear before enabling the
* IRQ if we had one, under which circumstance no event will be propagated
* anyway.
*
* The onus is on the client to perform a race-free check that it hasn't
* missed the event.
*/
rc = read_poll_timeout_atomic(aspeed_kcs_inb, str,
!(str & KCS_BMC_STR_OBF), 1, 100, false,
&priv->kcs_bmc, priv->kcs_bmc.ioreg.str);
/* Time for the slow path? */
if (rc == -ETIMEDOUT)
mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD);
} else {
del_timer(&priv->obe.timer);
}
}
if (mask & KCS_BMC_EVENT_TYPE_IBF) {
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note*/
/*
* Copyright (c) 2022, Ampere Computing LLC.
*/
#ifndef _UAPI_LINUX_IPMI_SSIF_BMC_H
#define _UAPI_LINUX_IPMI_SSIF_BMC_H
#include <linux/types.h>
/* Max length of ipmi ssif message included netfn and cmd field */
#define IPMI_SSIF_PAYLOAD_MAX 254
struct ipmi_ssif_msg {
unsigned int len;
__u8 payload[IPMI_SSIF_PAYLOAD_MAX];
};
#endif /* _UAPI_LINUX_IPMI_SSIF_BMC_H */
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