From 95099d4622f8cb224d94e314c7a8e0df60b13f87 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Sat, 09 Dec 2023 08:38:01 +0000
Subject: [PATCH] enable docker ppp
---
kernel/drivers/char/ipmi/ipmi_si_intf.c | 214 +++++++++++++++++++++++------------------------------
1 files changed, 93 insertions(+), 121 deletions(-)
diff --git a/kernel/drivers/char/ipmi/ipmi_si_intf.c b/kernel/drivers/char/ipmi/ipmi_si_intf.c
index 006d765..5eac94c 100644
--- a/kernel/drivers/char/ipmi/ipmi_si_intf.c
+++ b/kernel/drivers/char/ipmi/ipmi_si_intf.c
@@ -19,6 +19,8 @@
* and drives the real SMI state machine.
*/
+#define pr_fmt(fmt) "ipmi_si: " fmt
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/sched.h>
@@ -38,10 +40,9 @@
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
#include "ipmi_si.h"
+#include "ipmi_si_sm.h"
#include <linux/string.h>
#include <linux/ctype.h>
-
-#define PFX "ipmi_si: "
/* Measure times between events in the driver. */
#undef DEBUG_TIMING
@@ -71,7 +72,7 @@
static const char * const si_to_str[] = { "invalid", "kcs", "smic", "bt" };
-static int initialized;
+static bool initialized;
/*
* Indexes into stats[] in smi_info below.
@@ -232,14 +233,8 @@
/* From the get device id response... */
struct ipmi_device_id device_id;
- /* Default driver model device. */
- struct platform_device *pdev;
-
/* Have we added the device group to the device? */
bool dev_group_added;
-
- /* Have we added the platform device? */
- bool pdev_registered;
/* Counters and things for the proc filesystem. */
atomic_t stats[SI_NUM_STATS];
@@ -272,8 +267,8 @@
{
struct timespec64 t;
- getnstimeofday64(&t);
- pr_debug("**%s: %lld.%9.9ld\n", msg, (long long) t.tv_sec, t.tv_nsec);
+ ktime_get_ts64(&t);
+ pr_debug("**%s: %lld.%9.9ld\n", msg, t.tv_sec, t.tv_nsec);
}
#else
#define debug_timestamp(x)
@@ -940,42 +935,29 @@
}
/*
- * Use -1 in the nsec value of the busy waiting timespec to tell that
- * we are spinning in kipmid looking for something and not delaying
- * between checks
+ * Use -1 as a special constant to tell that we are spinning in kipmid
+ * looking for something and not delaying between checks
*/
-static inline void ipmi_si_set_not_busy(struct timespec64 *ts)
-{
- ts->tv_nsec = -1;
-}
-static inline int ipmi_si_is_busy(struct timespec64 *ts)
-{
- return ts->tv_nsec != -1;
-}
-
-static inline int ipmi_thread_busy_wait(enum si_sm_result smi_result,
- const struct smi_info *smi_info,
- struct timespec64 *busy_until)
+#define IPMI_TIME_NOT_BUSY ns_to_ktime(-1ull)
+static inline bool ipmi_thread_busy_wait(enum si_sm_result smi_result,
+ const struct smi_info *smi_info,
+ ktime_t *busy_until)
{
unsigned int max_busy_us = 0;
if (smi_info->si_num < num_max_busy_us)
max_busy_us = kipmid_max_busy_us[smi_info->si_num];
if (max_busy_us == 0 || smi_result != SI_SM_CALL_WITH_DELAY)
- ipmi_si_set_not_busy(busy_until);
- else if (!ipmi_si_is_busy(busy_until)) {
- getnstimeofday64(busy_until);
- timespec64_add_ns(busy_until, max_busy_us*NSEC_PER_USEC);
+ *busy_until = IPMI_TIME_NOT_BUSY;
+ else if (*busy_until == IPMI_TIME_NOT_BUSY) {
+ *busy_until = ktime_get() + max_busy_us * NSEC_PER_USEC;
} else {
- struct timespec64 now;
-
- getnstimeofday64(&now);
- if (unlikely(timespec64_compare(&now, busy_until) > 0)) {
- ipmi_si_set_not_busy(busy_until);
- return 0;
+ if (unlikely(ktime_get() > *busy_until)) {
+ *busy_until = IPMI_TIME_NOT_BUSY;
+ return false;
}
}
- return 1;
+ return true;
}
@@ -986,16 +968,15 @@
* that are not BT and do not have interrupts. It starts spinning
* when an operation is complete or until max_busy tells it to stop
* (if that is enabled). See the paragraph on kimid_max_busy_us in
- * Documentation/IPMI.txt for details.
+ * Documentation/driver-api/ipmi.rst for details.
*/
static int ipmi_thread(void *data)
{
struct smi_info *smi_info = data;
unsigned long flags;
enum si_sm_result smi_result;
- struct timespec64 busy_until;
+ ktime_t busy_until = IPMI_TIME_NOT_BUSY;
- ipmi_si_set_not_busy(&busy_until);
set_user_nice(current, MAX_NICE);
while (!kthread_should_stop()) {
int busy_wait;
@@ -1073,10 +1054,13 @@
atomic_set(&smi_info->req_events, 1);
}
-static void set_need_watch(void *send_info, bool enable)
+static void set_need_watch(void *send_info, unsigned int watch_mask)
{
struct smi_info *smi_info = send_info;
unsigned long flags;
+ int enable;
+
+ enable = !!watch_mask;
atomic_set(&smi_info->need_watch, enable);
spin_lock_irqsave(&smi_info->si_lock, flags);
@@ -1283,12 +1267,12 @@
rv = request_irq(io->irq,
ipmi_si_irq_handler,
IRQF_SHARED,
- DEVICE_NAME,
+ SI_DEVICE_NAME,
io->irq_handler_data);
if (rv) {
dev_warn(io->dev, "%s unable to claim interrupt %d,"
" running polled\n",
- DEVICE_NAME, io->irq);
+ SI_DEVICE_NAME, io->irq);
io->irq = 0;
} else {
io->irq_cleanup = std_irq_cleanup;
@@ -1332,6 +1316,7 @@
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)
@@ -1343,6 +1328,8 @@
*/
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);
@@ -1355,6 +1342,20 @@
/* 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);
@@ -1544,7 +1545,7 @@
rv = wait_for_msg_done(smi_info);
if (rv) {
- pr_warn(PFX "Error getting response from get global enables command, the event buffer is not enabled.\n");
+ pr_warn("Error getting response from get global enables command, the event buffer is not enabled\n");
goto out;
}
@@ -1555,7 +1556,7 @@
resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD ||
resp[2] != 0) {
- pr_warn(PFX "Invalid return from get global enables command, cannot enable the event buffer.\n");
+ pr_warn("Invalid return from get global enables command, cannot enable the event buffer\n");
rv = -EINVAL;
goto out;
}
@@ -1573,7 +1574,7 @@
rv = wait_for_msg_done(smi_info);
if (rv) {
- pr_warn(PFX "Error getting response from set global, enables command, the event buffer is not enabled.\n");
+ pr_warn("Error getting response from set global, enables command, the event buffer is not enabled\n");
goto out;
}
@@ -1583,7 +1584,7 @@
if (resp_len < 3 ||
resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 ||
resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) {
- pr_warn(PFX "Invalid return from get global, enables command, not enable the event buffer.\n");
+ pr_warn("Invalid return from get global, enables command, not enable the event buffer\n");
rv = -EINVAL;
goto out;
}
@@ -1603,37 +1604,37 @@
}
#define IPMI_SI_ATTR(name) \
-static ssize_t ipmi_##name##_show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
+static ssize_t name##_show(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
{ \
struct smi_info *smi_info = dev_get_drvdata(dev); \
\
return snprintf(buf, 10, "%u\n", smi_get_stat(smi_info, name)); \
} \
-static DEVICE_ATTR(name, S_IRUGO, ipmi_##name##_show, NULL)
+static DEVICE_ATTR(name, 0444, name##_show, NULL)
-static ssize_t ipmi_type_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t type_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct smi_info *smi_info = dev_get_drvdata(dev);
return snprintf(buf, 10, "%s\n", si_to_str[smi_info->io.si_type]);
}
-static DEVICE_ATTR(type, S_IRUGO, ipmi_type_show, NULL);
+static DEVICE_ATTR(type, 0444, type_show, NULL);
-static ssize_t ipmi_interrupts_enabled_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t interrupts_enabled_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct smi_info *smi_info = dev_get_drvdata(dev);
int enabled = smi_info->io.irq && !smi_info->interrupt_disabled;
return snprintf(buf, 10, "%d\n", enabled);
}
-static DEVICE_ATTR(interrupts_enabled, S_IRUGO,
- ipmi_interrupts_enabled_show, NULL);
+static DEVICE_ATTR(interrupts_enabled, 0444,
+ interrupts_enabled_show, NULL);
IPMI_SI_ATTR(short_timeouts);
IPMI_SI_ATTR(long_timeouts);
@@ -1647,16 +1648,16 @@
IPMI_SI_ATTR(watchdog_pretimeouts);
IPMI_SI_ATTR(incoming_messages);
-static ssize_t ipmi_params_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t params_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
struct smi_info *smi_info = dev_get_drvdata(dev);
return snprintf(buf, 200,
"%s,%s,0x%lx,rsp=%d,rsi=%d,rsh=%d,irq=%d,ipmb=%d\n",
si_to_str[smi_info->io.si_type],
- addr_space_to_str[smi_info->io.addr_type],
+ addr_space_to_str[smi_info->io.addr_space],
smi_info->io.addr_data,
smi_info->io.regspacing,
smi_info->io.regsize,
@@ -1664,7 +1665,7 @@
smi_info->io.irq,
smi_info->io.slave_addr);
}
-static DEVICE_ATTR(params, S_IRUGO, ipmi_params_show, NULL);
+static DEVICE_ATTR(params, 0444, params_show, NULL);
static struct attribute *ipmi_si_dev_attrs[] = {
&dev_attr_type.attr,
@@ -1845,8 +1846,7 @@
}
smi_info->timer_can_start = false;
- if (smi_info->timer_running)
- del_timer_sync(&smi_info->si_timer);
+ del_timer_sync(&smi_info->si_timer);
}
static struct smi_info *find_dup_si(struct smi_info *info)
@@ -1854,7 +1854,7 @@
struct smi_info *e;
list_for_each_entry(e, &smi_infos, link) {
- if (e->io.addr_type != info->io.addr_type)
+ if (e->io.addr_space != info->io.addr_space)
continue;
if (e->io.addr_data == info->io.addr_data) {
/*
@@ -1881,17 +1881,17 @@
* address, they presumably want us to use it and not what is
* in the firmware.
*/
- if (io->addr_source != SI_HARDCODED &&
- ipmi_si_hardcode_match(io->addr_type, io->addr_data)) {
+ if (io->addr_source != SI_HARDCODED && io->addr_source != SI_HOTMOD &&
+ ipmi_si_hardcode_match(io->addr_space, io->addr_data)) {
dev_info(io->dev,
"Hard-coded device at this address already exists");
return -ENODEV;
}
if (!io->io_setup) {
- if (io->addr_type == IPMI_IO_ADDR_SPACE) {
+ if (io->addr_space == IPMI_IO_ADDR_SPACE) {
io->io_setup = ipmi_si_port_setup;
- } else if (io->addr_type == IPMI_MEM_ADDR_SPACE) {
+ } else if (io->addr_space == IPMI_MEM_ADDR_SPACE) {
io->io_setup = ipmi_si_mem_setup;
} else {
return -EINVAL;
@@ -1926,7 +1926,7 @@
}
}
- pr_info(PFX "Adding %s-specified %s state machine\n",
+ pr_info("Adding %s-specified %s state machine\n",
ipmi_addr_src_to_str(new_smi->io.addr_source),
si_to_str[new_smi->io.si_type]);
@@ -1948,12 +1948,11 @@
{
int rv = 0;
int i;
- char *init_name = NULL;
- pr_info(PFX "Trying %s-specified %s state machine at %s address 0x%lx, slave address 0x%x, irq %d\n",
+ pr_info("Trying %s-specified %s state machine at %s address 0x%lx, slave address 0x%x, irq %d\n",
ipmi_addr_src_to_str(new_smi->io.addr_source),
si_to_str[new_smi->io.si_type],
- addr_space_to_str[new_smi->io.addr_type],
+ addr_space_to_str[new_smi->io.addr_space],
new_smi->io.addr_data,
new_smi->io.slave_addr, new_smi->io.irq);
@@ -1980,24 +1979,9 @@
/* Do this early so it's available for logs. */
if (!new_smi->io.dev) {
- init_name = kasprintf(GFP_KERNEL, "ipmi_si.%d",
- new_smi->si_num);
-
- /*
- * If we don't already have a device from something
- * else (like PCI), then register a new one.
- */
- new_smi->pdev = platform_device_alloc("ipmi_si",
- new_smi->si_num);
- if (!new_smi->pdev) {
- pr_err(PFX "Unable to allocate platform device\n");
- rv = -ENOMEM;
- goto out_err;
- }
- new_smi->io.dev = &new_smi->pdev->dev;
- new_smi->io.dev->driver = &ipmi_platform_driver.driver;
- /* Nulled by device_add() */
- new_smi->io.dev->init_name = init_name;
+ pr_err("IPMI interface added with no device\n");
+ rv = -EIO;
+ goto out_err;
}
/* Allocate the state machine's data and initialize it. */
@@ -2070,17 +2054,6 @@
atomic_set(&new_smi->req_events, 1);
}
- if (new_smi->pdev && !new_smi->pdev_registered) {
- rv = platform_device_add(new_smi->pdev);
- if (rv) {
- dev_err(new_smi->io.dev,
- "Unable to register system interface device: %d\n",
- rv);
- goto out_err;
- }
- new_smi->pdev_registered = true;
- }
-
dev_set_drvdata(new_smi->io.dev, new_smi);
rv = device_add_group(new_smi->io.dev, &ipmi_si_dev_attr_group);
if (rv) {
@@ -2116,7 +2089,6 @@
new_smi->io.io_cleanup = NULL;
}
- kfree(init_name);
return rv;
}
@@ -2129,7 +2101,8 @@
return 0;
ipmi_hardcode_init();
- pr_info("IPMI System Interface driver.\n");
+
+ pr_info("IPMI System Interface driver\n");
ipmi_si_platform_init();
@@ -2168,7 +2141,7 @@
}
skip_fallback_noirq:
- initialized = 1;
+ initialized = true;
mutex_unlock(&smi_infos_lock);
if (type)
@@ -2178,7 +2151,7 @@
if (unload_when_empty && list_empty(&smi_infos)) {
mutex_unlock(&smi_infos_lock);
cleanup_ipmi_si();
- pr_warn(PFX "Unable to find any System Interface(s)\n");
+ pr_warn("Unable to find any System Interface(s)\n");
return -ENODEV;
} else {
mutex_unlock(&smi_infos_lock);
@@ -2214,7 +2187,7 @@
* handlers might have been running before we freed the
* interrupt.
*/
- synchronize_sched();
+ synchronize_rcu();
/*
* Timeouts are stopped, now make sure the interrupts are off
@@ -2263,13 +2236,6 @@
if (smi_info->intf)
ipmi_unregister_smi(smi_info->intf);
- if (smi_info->pdev) {
- if (smi_info->pdev_registered)
- platform_device_unregister(smi_info->pdev);
- else
- platform_device_put(smi_info->pdev);
- }
-
kfree(smi_info);
}
@@ -2291,22 +2257,27 @@
return rv;
}
-void ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
- unsigned long addr)
+struct device *ipmi_si_remove_by_data(int addr_space, enum si_type si_type,
+ unsigned long addr)
{
/* remove */
struct smi_info *e, *tmp_e;
+ struct device *dev = NULL;
mutex_lock(&smi_infos_lock);
list_for_each_entry_safe(e, tmp_e, &smi_infos, link) {
- if (e->io.addr_type != addr_space)
+ if (e->io.addr_space != addr_space)
continue;
if (e->io.si_type != si_type)
continue;
- if (e->io.addr_data == addr)
+ if (e->io.addr_data == addr) {
+ dev = get_device(e->io.dev);
cleanup_one_si(e);
+ }
}
mutex_unlock(&smi_infos_lock);
+
+ return dev;
}
static void cleanup_ipmi_si(void)
@@ -2328,6 +2299,7 @@
mutex_unlock(&smi_infos_lock);
ipmi_si_hardcode_exit();
+ ipmi_si_hotmod_exit();
}
module_exit(cleanup_ipmi_si);
--
Gitblit v1.6.2