From e10e0c035c4c9bf9dd443a82e9ca220080770d81 Mon Sep 17 00:00:00 2001 From: Chong Qiao Date: Thu, 8 Jun 2023 20:24:21 +0800 Subject: [PATCH] ipmi_si: ls2k500 kcs driver add wait bmc reboot done and rebind support. LoongArch inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7CPCD -------------------------------- Signed-off-by: Chong Qiao Signed-off-by: Hongchen Zhang (cherry picked from commit b140ebe3bcd89d9b930ecd6d5c62f8c5cbf7582d) --- drivers/char/ipmi/btlock.h | 6 +++++- drivers/char/ipmi/ipmi_si_ls2k500.c | 28 +++++++++++++++++++++++++--- drivers/video/fbdev/ls2k500sfb.c | 6 +++++- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/drivers/char/ipmi/btlock.h b/drivers/char/ipmi/btlock.h index 28eae10cf41c..cf585e42d42d 100644 --- a/drivers/char/ipmi/btlock.h +++ b/drivers/char/ipmi/btlock.h @@ -19,6 +19,7 @@ static inline int btlock_lock(volatile union btlock *p, int n, unsigned char del { union btlock t, t1; unsigned long flags; + unsigned long c0 = get_cycles(), c1; if (n > 1) return -1; @@ -39,7 +40,10 @@ static inline int btlock_lock(volatile union btlock *p, int n, unsigned char del t.u = p->u; wmb(); /* flush write out immediately */ local_irq_restore(flags); - ndelay(((t.b[1 - n] & 0x7f) + (get_cycles() & 1)) * 100); + c1 = get_cycles(); + if (c1 - c0 > *mscycles * 1000) + return -1; + ndelay(((t.b[1 - n] & 0x7f) + (c1 & 1)) * 100); } return 0; } diff --git a/drivers/char/ipmi/ipmi_si_ls2k500.c b/drivers/char/ipmi/ipmi_si_ls2k500.c index 9afe52928de8..9a1be53e8a0b 100644 --- a/drivers/char/ipmi/ipmi_si_ls2k500.c +++ b/drivers/char/ipmi/ipmi_si_ls2k500.c @@ -18,17 +18,31 @@ #include #include #include "ipmi_si.h" +static unsigned long *mscycles; +static unsigned long *event_jiffies; #include "kcs_bmc_ls2k500.h" +static int resetbootwait = 60; +module_param(resetbootwait, int, 0664); #define KCS_STATUS_CMD_DAT BIT(3) +static int pcie_busy(void) +{ + if (time_before(jiffies, *event_jiffies + resetbootwait*HZ)) + return -1; + return 0; +} + static unsigned char intf_sim_inb(const struct si_sm_io *io, unsigned int offset) { IPMIKCS *ik = io->addr_source_data; uint32_t ret; - btlock_lock(&ik->lock, 0, 1); + if (pcie_busy()) + return 0; + if (btlock_lock(&ik->lock, 0, 1) < 0) + return 0; switch (offset & 1) { case 0: ret = ik->data_out_reg; @@ -47,7 +61,10 @@ static void intf_sim_outb(const struct si_sm_io *io, unsigned int offset, { IPMIKCS *ik = io->addr_source_data; - btlock_lock(&ik->lock, 0, 1); + if (pcie_busy()) + return; + if (btlock_lock(&ik->lock, 0, 1) < 0) + return; if (IPMI_KCS_GET_IBF(ik->status_reg)) goto out; @@ -86,7 +103,7 @@ static int of_ipmi_ls2k500_probe(struct platform_device *pdev) { int rv; struct si_sm_io io; - + void **kcs_data; memset(&io, 0, sizeof(io)); io.addr_source = SI_PLATFORM; dev_info(&pdev->dev, "probing via ls2k500 platform"); @@ -100,6 +117,9 @@ static int of_ipmi_ls2k500_probe(struct platform_device *pdev) io.addr_source_data = ioremap(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); + kcs_data = dev_get_platdata(&pdev->dev); + event_jiffies = kcs_data[0]; + mscycles = kcs_data[1]; io.dev = &pdev->dev; io.regspacing = 4; io.regsize = DEFAULT_REGSIZE; @@ -112,6 +132,8 @@ static int of_ipmi_ls2k500_probe(struct platform_device *pdev) &pdev->resource[0], io.regsize, io.regspacing, io.irq); rv = ipmi_si_add_smi(&io); + if (rv) + ipmi_si_remove_by_dev(&pdev->dev); return rv; } diff --git a/drivers/video/fbdev/ls2k500sfb.c b/drivers/video/fbdev/ls2k500sfb.c index 7ae97ec9d0ce..162ec6dc48ca 100644 --- a/drivers/video/fbdev/ls2k500sfb.c +++ b/drivers/video/fbdev/ls2k500sfb.c @@ -108,6 +108,7 @@ static void ls2k500sfb_redraw_fn(struct work_struct *work) switch_console(saved_console); } +static unsigned long event_jiffies; static void ls2k500sfb_events_fn(struct work_struct *work) { struct ls2k500sfb_struct *priv = container_of(work, struct ls2k500sfb_struct, work); @@ -148,6 +149,7 @@ static void ls2k500sfb_events_fn(struct work_struct *work) pci_write_config_dword(ppdev, 0x18, 0); pci_write_config_dword(ppdev, 0x1c, 0); pci_write_config_dword(ppdev, 0x20, 0); + event_jiffies = jiffies; atomic_set(&waiting_for_pciebreak_ipi, 0); wmb(); /* flush all write after change pcie window */ local_bh_enable(); @@ -645,6 +647,7 @@ static struct platform_driver simplefb_driver = { .remove = simplefb_remove, }; +static void *kcs_data[2] = {&event_jiffies, &mscycles}; static int ls2k500sfb_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct simplefb_platform_data mode; @@ -737,7 +740,8 @@ static int ls2k500sfb_probe(struct pci_dev *dev, const struct pci_device_id *id) for (i = 0; i < 5; i++) { res[0].start = phybase + 0x00f00000 + 0x1c*i; res[0].end = phybase + 0x00f00000 + 0x1c*(i+1) - 1; - platform_device_register_simple("ipmi_ls2k500_si", i, res, 1); + platform_device_register_resndata(NULL, "ipmi_ls2k500_si", i, res, 1, + kcs_data, sizeof(kcs_data)); } return PTR_ERR_OR_ZERO(pd); -- Gitee