From 4617721c502b2ddaa4e324e86da4997edf738fa5 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Wed, 2 Sep 2026 09:55:01 -0400 Subject: ftrace: Synchronize the initialization of ftrace_ops There's some internal state that ftrace_ops needs to have set, but since it can be declared outside of the ftrace.c code, it calls ftrace_ops_init() on the ops in every global function. The issue is that if two tasks call it on the same ops at the same time it is possible to have the initialization of one corrupt the initialization of the other call. Create a ops_mutex to use to synchronize every initialization of the ftrace_ops. The mutex is taken within checking the ftrace_ops flag that states it was initializied but the flag is checked again after the mutex has been taken. Checking first outside the mutex allows it to shortcut having to take the mutex. But then the check needs to be done again after the mute is taken in case of races. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock") Reported-by: sashiko-bot@kernel.org Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/ Signed-off-by: Steven Rostedt --- drivers/video/fbdev/i810/Makefile | 18 + drivers/video/fbdev/i810/i810-i2c.c | 175 +++ drivers/video/fbdev/i810/i810.h | 298 +++++ drivers/video/fbdev/i810/i810_accel.c | 456 +++++++ drivers/video/fbdev/i810/i810_dvt.c | 313 +++++ drivers/video/fbdev/i810/i810_gtf.c | 276 ++++ drivers/video/fbdev/i810/i810_main.c | 2234 +++++++++++++++++++++++++++++++++ drivers/video/fbdev/i810/i810_main.h | 69 + drivers/video/fbdev/i810/i810_regs.h | 275 ++++ 9 files changed, 4114 insertions(+) create mode 100644 drivers/video/fbdev/i810/Makefile create mode 100644 drivers/video/fbdev/i810/i810-i2c.c create mode 100644 drivers/video/fbdev/i810/i810.h create mode 100644 drivers/video/fbdev/i810/i810_accel.c create mode 100644 drivers/video/fbdev/i810/i810_dvt.c create mode 100644 drivers/video/fbdev/i810/i810_gtf.c create mode 100644 drivers/video/fbdev/i810/i810_main.c create mode 100644 drivers/video/fbdev/i810/i810_main.h create mode 100644 drivers/video/fbdev/i810/i810_regs.h (limited to 'drivers/video/fbdev/i810') diff --git a/drivers/video/fbdev/i810/Makefile b/drivers/video/fbdev/i810/Makefile new file mode 100644 index 000000000..3e466510f --- /dev/null +++ b/drivers/video/fbdev/i810/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the Intel 810/815 framebuffer driver +# + +obj-$(CONFIG_FB_I810) += i810fb.o + +i810fb-objs := i810_main.o i810_accel.o + +ifdef CONFIG_FB_I810_GTF +i810fb-objs += i810_gtf.o +else +i810fb-objs += i810_dvt.o +endif + +ifdef CONFIG_FB_I810_I2C +i810fb-objs += i810-i2c.o +endif diff --git a/drivers/video/fbdev/i810/i810-i2c.c b/drivers/video/fbdev/i810/i810-i2c.c new file mode 100644 index 000000000..7db17d0d8 --- /dev/null +++ b/drivers/video/fbdev/i810/i810-i2c.c @@ -0,0 +1,175 @@ + /*-*- linux-c -*- + * linux/drivers/video/i810-i2c.c -- Intel 810/815 I2C support + * + * Copyright (C) 2004 Antonino Daplas + * All Rights Reserved + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ +#include +#include +#include +#include +#include +#include +#include "i810.h" +#include "i810_regs.h" +#include "i810_main.h" +#include "../edid.h" + +/* bit locations in the registers */ +#define SCL_DIR_MASK 0x0001 +#define SCL_DIR 0x0002 +#define SCL_VAL_MASK 0x0004 +#define SCL_VAL_OUT 0x0008 +#define SCL_VAL_IN 0x0010 +#define SDA_DIR_MASK 0x0100 +#define SDA_DIR 0x0200 +#define SDA_VAL_MASK 0x0400 +#define SDA_VAL_OUT 0x0800 +#define SDA_VAL_IN 0x1000 + +#define DEBUG /* define this for verbose EDID parsing output */ + +#ifdef DEBUG +#define DPRINTK(fmt, args...) printk(fmt,## args) +#else +#define DPRINTK(fmt, args...) +#endif + +static void i810i2c_setscl(void *data, int state) +{ + struct i810fb_i2c_chan *chan = data; + struct i810fb_par *par = chan->par; + u8 __iomem *mmio = par->mmio_start_virtual; + + if (state) + i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK | SCL_VAL_MASK); + else + i810_writel(mmio, chan->ddc_base, SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK); + i810_readl(mmio, chan->ddc_base); /* flush posted write */ +} + +static void i810i2c_setsda(void *data, int state) +{ + struct i810fb_i2c_chan *chan = data; + struct i810fb_par *par = chan->par; + u8 __iomem *mmio = par->mmio_start_virtual; + + if (state) + i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK | SDA_VAL_MASK); + else + i810_writel(mmio, chan->ddc_base, SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK); + i810_readl(mmio, chan->ddc_base); /* flush posted write */ +} + +static int i810i2c_getscl(void *data) +{ + struct i810fb_i2c_chan *chan = data; + struct i810fb_par *par = chan->par; + u8 __iomem *mmio = par->mmio_start_virtual; + + i810_writel(mmio, chan->ddc_base, SCL_DIR_MASK); + i810_writel(mmio, chan->ddc_base, 0); + return ((i810_readl(mmio, chan->ddc_base) & SCL_VAL_IN) != 0); +} + +static int i810i2c_getsda(void *data) +{ + struct i810fb_i2c_chan *chan = data; + struct i810fb_par *par = chan->par; + u8 __iomem *mmio = par->mmio_start_virtual; + + i810_writel(mmio, chan->ddc_base, SDA_DIR_MASK); + i810_writel(mmio, chan->ddc_base, 0); + return ((i810_readl(mmio, chan->ddc_base) & SDA_VAL_IN) != 0); +} + +static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name) +{ + int rc; + + strcpy(chan->adapter.name, name); + chan->adapter.owner = THIS_MODULE; + chan->adapter.algo_data = &chan->algo; + chan->adapter.dev.parent = &chan->par->dev->dev; + chan->algo.setsda = i810i2c_setsda; + chan->algo.setscl = i810i2c_setscl; + chan->algo.getsda = i810i2c_getsda; + chan->algo.getscl = i810i2c_getscl; + chan->algo.udelay = 10; + chan->algo.timeout = (HZ/2); + chan->algo.data = chan; + + i2c_set_adapdata(&chan->adapter, chan); + + /* Raise SCL and SDA */ + chan->algo.setsda(chan, 1); + chan->algo.setscl(chan, 1); + udelay(20); + + rc = i2c_bit_add_bus(&chan->adapter); + + if (rc == 0) + dev_dbg(&chan->par->dev->dev, "I2C bus %s registered.\n",name); + else { + dev_warn(&chan->par->dev->dev, "Failed to register I2C bus " + "%s.\n", name); + chan->par = NULL; + } + + return rc; +} + +void i810_create_i2c_busses(struct i810fb_par *par) +{ + par->chan[0].par = par; + par->chan[1].par = par; + par->chan[2].par = par; + + par->chan[0].ddc_base = GPIOA; + i810_setup_i2c_bus(&par->chan[0], "I810-DDC"); + par->chan[1].ddc_base = GPIOB; + i810_setup_i2c_bus(&par->chan[1], "I810-I2C"); + par->chan[2].ddc_base = GPIOC; + i810_setup_i2c_bus(&par->chan[2], "I810-GPIOC"); +} + +void i810_delete_i2c_busses(struct i810fb_par *par) +{ + if (par->chan[0].par) + i2c_del_adapter(&par->chan[0].adapter); + par->chan[0].par = NULL; + + if (par->chan[1].par) + i2c_del_adapter(&par->chan[1].adapter); + par->chan[1].par = NULL; + + if (par->chan[2].par) + i2c_del_adapter(&par->chan[2].adapter); + par->chan[2].par = NULL; +} + +int i810_probe_i2c_connector(struct fb_info *info, u8 **out_edid, int conn) +{ + struct i810fb_par *par = info->par; + u8 *edid = NULL; + + DPRINTK("i810-i2c: Probe DDC%i Bus\n", conn+1); + if (conn < par->ddc_num) { + edid = fb_ddc_read(&par->chan[conn].adapter); + } else { + const u8 *e = fb_firmware_edid(info->device); + + if (e != NULL) { + DPRINTK("i810-i2c: Getting EDID from BIOS\n"); + edid = kmemdup(e, EDID_LENGTH, GFP_KERNEL); + } + } + + *out_edid = edid; + + return (edid) ? 0 : 1; +} diff --git a/drivers/video/fbdev/i810/i810.h b/drivers/video/fbdev/i810/i810.h new file mode 100644 index 000000000..7b1c002bf --- /dev/null +++ b/drivers/video/fbdev/i810/i810.h @@ -0,0 +1,298 @@ +/*-*- linux-c -*- + * linux/drivers/video/i810.h -- Intel 810 General Definitions/Declarations + * + * Copyright (C) 2001 Antonino Daplas + * All Rights Reserved + * + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#ifndef __I810_H__ +#define __I810_H__ + +#include +#include +#include +#include +#include +#include